Merge Mainline
This commit is contained in:
commit
5600477a3d
@ -6,13 +6,13 @@ ifdef CONFIG_TESTING_KERNEL
|
||||
KERNEL_PATCHVER:=$(KERNEL_TESTING_PATCHVER)
|
||||
endif
|
||||
|
||||
LINUX_VERSION-4.9 = .228
|
||||
LINUX_VERSION-4.14 = .186
|
||||
LINUX_VERSION-4.9 = .229
|
||||
LINUX_VERSION-4.14 = .187
|
||||
LINUX_VERSION-4.19 = .130
|
||||
LINUX_VERSION-5.4 = .48
|
||||
|
||||
LINUX_KERNEL_HASH-4.9.228 = 8fbff429c6453036a0f79a55b4d85c1885c16999751198ddefdca7a3ff17fc34
|
||||
LINUX_KERNEL_HASH-4.14.186 = 445b426181005b157a0cd33d663ed61a73c32c669772e066bb30291c6775a260
|
||||
LINUX_KERNEL_HASH-4.9.229 = 3256c2835fd95a1a739603e78b02d363eac2ce73a39fa19b13b32da4fc370fdc
|
||||
LINUX_KERNEL_HASH-4.14.187 = 5b223475eaeea196aa7e127d3f253bca5c35d8afdc72ca75230ce1ecdd1454bd
|
||||
LINUX_KERNEL_HASH-4.19.130 = a692c0e61dc885b4d6e66ae7bf202dadf7d5538fbf92766ce7cf8e227fd4f00f
|
||||
LINUX_KERNEL_HASH-5.4.48 = bf20ddafcd04c114d34654bb10d1eb74f1864f3d14b676c6f0d42d60bbcf1d53
|
||||
|
||||
|
||||
@ -8,13 +8,13 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=v2ray-plugin
|
||||
PKG_VERSION:=1.3.1
|
||||
PKG_VERSION:=1.3.2
|
||||
PKG_RELEASE:=2
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/shadowsocks/v2ray-plugin/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=86d37a8ecef82457b4750a1af9e8d093b25ae0d32ea7dcc2ad5c0068fe2d3d74
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/teddysun/v2ray-plugin/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=1cc9ed8e79347da044fa2f577bc5371dcdf0b03e131f61137b5c1d2a2be11509
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
@ -8,12 +8,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=linux-firmware
|
||||
PKG_VERSION:=20200122
|
||||
PKG_VERSION:=20200619
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||
PKG_HASH:=a30e811b3736a72b874ac27e10662f5e5409b1cadf8aab7ba88e8f8bc8083986
|
||||
PKG_HASH:=962d3ae197d226c8259f9cc7746f7ef12a9d23787cd56bd27302021ba6339722
|
||||
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
|
||||
@ -163,7 +163,7 @@ endef
|
||||
$(eval $(call KernelPackage,fs-efivarfs))
|
||||
|
||||
|
||||
define KernelPackage/fs-exfat-kernel
|
||||
define KernelPackage/fs-exfat
|
||||
SUBMENU:=$(FS_MENU)
|
||||
TITLE:=exFAT filesystem support
|
||||
KCONFIG:= \
|
||||
@ -177,14 +177,14 @@ define KernelPackage/fs-exfat-kernel
|
||||
CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8"
|
||||
FILES:=$(LINUX_DIR)/drivers/staging/exfat/exfat.ko
|
||||
AUTOLOAD:=$(call AutoLoad,30,exfat,1)
|
||||
DEPENDS:=@!(LINUX_4_9||LINUX_4_14||LINUX_4_19) +kmod-nls-base
|
||||
DEPENDS:=@LINUX_5_4 +kmod-nls-base
|
||||
endef
|
||||
|
||||
define KernelPackage/fs-exfat-kernel/description
|
||||
define KernelPackage/fs-exfat/description
|
||||
Kernel module for exFAT filesystem support
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,fs-exfat-kernel))
|
||||
$(eval $(call KernelPackage,fs-exfat))
|
||||
|
||||
|
||||
define KernelPackage/fs-exportfs
|
||||
|
||||
@ -282,6 +282,7 @@ define KernelPackage/drm-amdgpu
|
||||
CONFIG_DRM_AMDGPU_SI=y \
|
||||
CONFIG_DRM_AMDGPU_CIK=y \
|
||||
CONFIG_DRM_AMD_DC=y \
|
||||
CONFIG_HSA_AMD=y \
|
||||
CONFIG_DEBUG_KERNEL_DC=n
|
||||
FILES:=$(LINUX_DIR)/drivers/gpu/drm/amd/amdgpu/amdgpu.ko \
|
||||
$(LINUX_DIR)/drivers/gpu/drm/scheduler/gpu-sched.ko@ge4.15 \
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=UnblockNeteaseMusic-Go
|
||||
PKG_VERSION:=0.2.0
|
||||
PKG_RELEASE:=3
|
||||
PKG_VERSION:=0.2.1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/cnsilvan/UnblockNeteaseMusic.git
|
||||
PKG_SOURCE_VERSION:=0c1c2f7ed9ae6277a10b1b1bba81101f552af509
|
||||
PKG_SOURCE_VERSION:=7664b2b5c5dbe8e1ff7fde0c0051b4feabc0e0ba
|
||||
PKG_MAINTAINER:=Silvan <cnsilvan@gmail.com>
|
||||
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
|
||||
@ -27,6 +27,19 @@ GO_PKG_LDFLAGS+= \
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
|
||||
|
||||
define Package/$(PKG_NAME)/config
|
||||
config $(PKG_NAME)_INCLUDE_GOPROXY
|
||||
bool "Compiling with GOPROXY proxy"
|
||||
default n
|
||||
|
||||
endef
|
||||
|
||||
ifeq ($(CONFIG_$(PKG_NAME)_INCLUDE_GOPROXY),y)
|
||||
export GO111MODULE=on
|
||||
export GOPROXY=https://goproxy.io
|
||||
#export GOPROXY=https://mirrors.aliyun.com/goproxy/
|
||||
endif
|
||||
|
||||
define Package/$(PKG_NAME)
|
||||
SECTION:=multimedia
|
||||
CATEGORY:=Multimedia
|
||||
@ -44,7 +57,6 @@ define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
patch -p1 -d $(BUILD_DIR)/$(PKG_NAME) <./patches/01-fix-endpoint.patch
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
diff --git a/processor/processor.go b/processor/processor.go
|
||||
index a35f8df..a7e3015 100644
|
||||
--- a/processor/processor.go
|
||||
+++ b/processor/processor.go
|
||||
@@ -393,7 +393,7 @@
|
||||
//data["url"] = uri.Scheme + "://" + uri.Host + uri.EscapedPath()
|
||||
//data["url"] = uri.String()
|
||||
if *config.EndPoint {
|
||||
- data["url"] = "http://music.163.com/unblockmusic/" + uri.String()
|
||||
+ data["url"] = "https://music.163.com/unblockmusic/" + uri.String()
|
||||
} else {
|
||||
data["url"] = uri.String()
|
||||
}
|
||||
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=automount
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=31
|
||||
PKG_RELEASE:=32
|
||||
PKG_ARCH:=all
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
@ -17,7 +17,7 @@ include $(INCLUDE_DIR)/package.mk
|
||||
define Package/automount
|
||||
TITLE:=Mount autoconfig hotplug script.
|
||||
MAINTAINER:=Lean
|
||||
DEPENDS:=+block-mount +kmod-usb-storage +kmod-usb-storage-extras +!TARGET_ramips:kmod-usb-storage-uas +kmod-fs-vfat +kmod-fs-ext4 +ntfs-3g +(LINUX_4_9||LINUX_4_14||LINUX_4_19):kmod-fs-exfat +LINUX_5_4:kmod-fs-exfat-kernel
|
||||
DEPENDS:=+block-mount +kmod-usb-storage +kmod-usb-storage-extras +!TARGET_ramips:kmod-usb-storage-uas +kmod-fs-vfat +kmod-fs-ext4 +!LINUX_5_4:kmod-fs-exfat0 +LINUX_5_4:kmod-fs-exfat +ntfs-3g
|
||||
endef
|
||||
|
||||
define Package/automount/description
|
||||
|
||||
@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=baidupcs-web
|
||||
PKG_VERSION:=3.7.1
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@ -62,7 +62,7 @@ endif
|
||||
|
||||
PKG_SOURCE:=BaiduPCS-Go-v$(PKG_VERSION)-linux-$(PKG_ARCH_BAIDUPCS-WEB).zip
|
||||
|
||||
PKG_SOURCE_URL:=https://github.com/Erope/baidupcs-web/releases/download/$(PKG_VERSION)/
|
||||
PKG_SOURCE_URL:=https://github.com/coolsnowwolf/baidupcs-web/raw/master/
|
||||
|
||||
UNZIP_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)/$(PKG_NAME)-unzip
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=default-settings
|
||||
PKG_VERSION:=1.1
|
||||
PKG_RELEASE:=60
|
||||
PKG_RELEASE:=61
|
||||
PKG_LICENSE:=GPLv3
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
||||
|
||||
@ -8,5 +8,5 @@
|
||||
[0;1;30;90m│[0m [0;1;34;94m#[0m [0;37m│[0m
|
||||
[0;1;34;94m│[0m [0;1;34;94m"[0m [0;1;34;94m│[0m
|
||||
[0;1;34;94m│───────────────[0;34m────────────────[0;37m────────────────[0;1;34;94m──│[0m
|
||||
[0;1;34;94m│[0m [0;1;34;94mOpenWrt[0m [0;1;34;94m18.06[0m [0;1;34;94mby[0m [0;1;34;94mLean[0m [0;37m|[0m [0;1;34;94mMod [0;1;34;94m20.06[0m [0;1;34;94mBy[0m [0;1;34;94mCTCGFW[0m [0;1;34;94m│[0m
|
||||
[0;1;34;94m│[0m [0;1;34;94mOpenWrt[0m [0;1;34;94m18.06[0m [0;1;34;94mby[0m [0;1;34;94mLean[0m [0;37m|[0m [0;1;34;94mMod [0;1;34;94m20.07[0m [0;1;34;94mBy[0m [0;1;34;94mCTCGFW[0m [0;1;34;94m│[0m
|
||||
[0;1;34;94m└───────[0;34m────────────────[0;37m────────────────[0;1;30;90m───────[0;1;34;94m───┘[0m
|
||||
|
||||
@ -45,13 +45,13 @@ sed -i '/option disabled/d' /etc/config/wireless
|
||||
sed -i '/set wireless.radio${devidx}.disabled/d' /lib/wifi/mac80211.sh
|
||||
|
||||
sed -i '/DISTRIB_REVISION/d' /etc/openwrt_release
|
||||
echo "DISTRIB_REVISION='| Mod20.06 by CTCGFW'" >> /etc/openwrt_release
|
||||
echo "DISTRIB_REVISION='| Mod20.07 by CTCGFW'" >> /etc/openwrt_release
|
||||
sed -i '/DISTRIB_DESCRIPTION/d' /etc/openwrt_release
|
||||
echo "DISTRIB_DESCRIPTION='OpenWrt 18.06 by Lean '" >> /etc/openwrt_release
|
||||
|
||||
sed -i 's/LuCI openwrt-18.06 branch/LuCI 18.06 by Lean/g' /usr/lib/lua/luci/version.lua
|
||||
sed -i '/luciversion/d' /usr/lib/lua/luci/version.lua
|
||||
echo 'luciversion = "Mod20.05 by CTCGFW"' >> /usr/lib/lua/luci/version.lua
|
||||
echo 'luciversion = "Mod20.06 by CTCGFW"' >> /usr/lib/lua/luci/version.lua
|
||||
|
||||
sed -i '/log-facility/d' /etc/dnsmasq.conf
|
||||
echo "log-facility=/dev/null" >> /etc/dnsmasq.conf
|
||||
|
||||
91
package/lean/fast-classifier/Makefile
Normal file
91
package/lean/fast-classifier/Makefile
Normal file
@ -0,0 +1,91 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=fast-classifier
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define KernelPackage/$(PKG_NAME)/Default
|
||||
SECTION:=kernel
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Network Support
|
||||
DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe
|
||||
TITLE:=Kernel driver for FAST Classifier
|
||||
FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko
|
||||
KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y CONFIG_NF_CONNTRACK_MARK=y
|
||||
PROVIDES:=$(PKG_NAME)
|
||||
endef
|
||||
|
||||
define KernelPackage/$(PKG_NAME)
|
||||
$(call KernelPackage/$(PKG_NAME)/Default)
|
||||
endef
|
||||
|
||||
define KernelPackage/$(PKG_NAME)-noload
|
||||
$(call KernelPackage/$(PKG_NAME)/Default)
|
||||
endef
|
||||
|
||||
define KernelPackage/$(PKG_NAME)/Default/description
|
||||
FAST Classifier talks to SFE to make decisions about offloading connections
|
||||
endef
|
||||
|
||||
define KernelPackage/$(PKG_NAME)/description
|
||||
$(call KernelPackage/$(PKG_NAME)/Default/description)
|
||||
endef
|
||||
|
||||
define KernelPackage/$(PKG_NAME)-noload/description
|
||||
$(call KernelPackage/$(PKG_NAME)/Default/description)
|
||||
|
||||
This package does not load $(PKG_NAME) at boot by default
|
||||
endef
|
||||
|
||||
define Package/fast-classifier-example
|
||||
TITLE:=Example user space program for fast-classifier
|
||||
DEPENDS:=+libnl +kmod-fast-classifier
|
||||
endef
|
||||
|
||||
define Package/fast-classifier-example/description
|
||||
Example user space program that communicates with fast
|
||||
classifier kernel module
|
||||
endef
|
||||
|
||||
SFE_MAKE_OPTS:=SFE_SUPPORT_IPV6=y
|
||||
|
||||
define Build/Compile/kmod
|
||||
+$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" $(strip $(SFE_MAKE_OPTS)) \
|
||||
$(KERNEL_MAKE_FLAGS) \
|
||||
$(PKG_MAKE_FLAGS) \
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
CONFIG_FAST_CLASSIFIER=m \
|
||||
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
|
||||
modules
|
||||
endef
|
||||
|
||||
define Build/Compile/example
|
||||
$(TARGET_CC) -o $(PKG_BUILD_DIR)/userspace_fast_classifier \
|
||||
-I $(PKG_BUILD_DIR) \
|
||||
-I$(STAGING_DIR)/usr/include/libnl \
|
||||
-I$(STAGING_DIR)/usr/include/libnl3 \
|
||||
-lnl-genl-3 -lnl-3 \
|
||||
$(PKG_BUILD_DIR)/nl_classifier_test.c
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(Build/Compile/kmod)
|
||||
$(if $(CONFIG_PACKAGE_fast-classifier-example),$(Build/Compile/example))
|
||||
endef
|
||||
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) $(1)/usr/include
|
||||
$(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/
|
||||
endef
|
||||
|
||||
|
||||
define Package/fast-classifier-example/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,$(PKG_NAME)))
|
||||
$(eval $(call KernelPackage,$(PKG_NAME)-noload))
|
||||
$(eval $(call BuildPackage,fast-classifier-example))
|
||||
10
package/lean/fast-classifier/src/Makefile
Normal file
10
package/lean/fast-classifier/src/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
obj-$(CONFIG_FAST_CLASSIFIER) += fast-classifier.o
|
||||
|
||||
ifeq ($(SFE_SUPPORT_IPV6),)
|
||||
SFE_SUPPORT_IPV6=y
|
||||
endif
|
||||
ccflags-$(SFE_SUPPORT_IPV6) += -DSFE_SUPPORT_IPV6
|
||||
|
||||
ccflags-y += -I$(obj)/../shortcut-fe
|
||||
|
||||
obj ?= .
|
||||
@ -3,7 +3,7 @@
|
||||
* Shortcut forwarding engine connection manager.
|
||||
* fast-classifier
|
||||
*
|
||||
* Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all copies.
|
||||
@ -29,17 +29,16 @@
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_timeout.h>
|
||||
#include <linux/netfilter/xt_dscp.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "sfe_backport.h"
|
||||
#include "sfe.h"
|
||||
#include "sfe_cm.h"
|
||||
#include <sfe_backport.h>
|
||||
#include <sfe.h>
|
||||
#include <sfe_cm.h>
|
||||
#include "fast-classifier.h"
|
||||
|
||||
typedef enum fast_classifier_exception {
|
||||
@ -111,14 +110,16 @@ struct fast_classifier {
|
||||
u32 exceptions[FAST_CL_EXCEPTION_MAX];
|
||||
};
|
||||
|
||||
static struct fast_classifier __fsc;
|
||||
static struct fast_classifier __sc;
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
|
||||
static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = {
|
||||
[FAST_CLASSIFIER_A_TUPLE] = {
|
||||
.type = NLA_UNSPEC,
|
||||
.len = sizeof(struct fast_classifier_tuple)
|
||||
},
|
||||
};
|
||||
#endif /*KERNEL_VERSION(5, 2, 0)*/
|
||||
|
||||
static struct genl_multicast_group fast_classifier_genl_mcgrp[] = {
|
||||
{
|
||||
@ -126,14 +127,6 @@ static struct genl_multicast_group fast_classifier_genl_mcgrp[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family fast_classifier_gnl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.hdrsize = FAST_CLASSIFIER_GENL_HDRSIZE,
|
||||
.name = FAST_CLASSIFIER_GENL_NAME,
|
||||
.version = FAST_CLASSIFIER_GENL_VERSION,
|
||||
.maxattr = FAST_CLASSIFIER_A_MAX,
|
||||
};
|
||||
|
||||
static int fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info);
|
||||
static int fast_classifier_nl_genl_msg_DUMP(struct sk_buff *skb, struct netlink_callback *cb);
|
||||
|
||||
@ -141,26 +134,48 @@ static struct genl_ops fast_classifier_gnl_ops[] = {
|
||||
{
|
||||
.cmd = FAST_CLASSIFIER_C_OFFLOAD,
|
||||
.flags = 0,
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
|
||||
.policy = fast_classifier_genl_policy,
|
||||
#endif /*KERNEL_VERSION(5, 2, 0)*/
|
||||
.doit = fast_classifier_offload_genl_msg,
|
||||
.dumpit = NULL,
|
||||
},
|
||||
{
|
||||
.cmd = FAST_CLASSIFIER_C_OFFLOADED,
|
||||
.flags = 0,
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
|
||||
.policy = fast_classifier_genl_policy,
|
||||
#endif /*KERNEL_VERSION(5, 2, 0)*/
|
||||
.doit = NULL,
|
||||
.dumpit = fast_classifier_nl_genl_msg_DUMP,
|
||||
},
|
||||
{
|
||||
.cmd = FAST_CLASSIFIER_C_DONE,
|
||||
.flags = 0,
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0))
|
||||
.policy = fast_classifier_genl_policy,
|
||||
#endif /*KERNEL_VERSION(5, 2, 0)*/
|
||||
.doit = NULL,
|
||||
.dumpit = fast_classifier_nl_genl_msg_DUMP,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family fast_classifier_gnl_family = {
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0))
|
||||
.id = GENL_ID_GENERATE,
|
||||
#endif /*KERNEL_VERSION(4, 10, 0)*/
|
||||
.hdrsize = FAST_CLASSIFIER_GENL_HDRSIZE,
|
||||
.name = FAST_CLASSIFIER_GENL_NAME,
|
||||
.version = FAST_CLASSIFIER_GENL_VERSION,
|
||||
.maxattr = FAST_CLASSIFIER_A_MAX,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
|
||||
.ops = fast_classifier_gnl_ops,
|
||||
.n_ops = ARRAY_SIZE(fast_classifier_gnl_ops),
|
||||
.mcgrps = fast_classifier_genl_mcgrp,
|
||||
.n_mcgrps = ARRAY_SIZE(fast_classifier_genl_mcgrp),
|
||||
#endif /*KERNEL_VERSION(4, 10, 0)*/
|
||||
};
|
||||
|
||||
static atomic_t offload_msgs = ATOMIC_INIT(0);
|
||||
static atomic_t offload_no_match_msgs = ATOMIC_INIT(0);
|
||||
static atomic_t offloaded_msgs = ATOMIC_INIT(0);
|
||||
@ -189,7 +204,7 @@ static bool skip_to_bridge_ingress;
|
||||
*/
|
||||
static inline void fast_classifier_incr_exceptions(fast_classifier_exception_t except)
|
||||
{
|
||||
struct fast_classifier *sc = &__fsc;
|
||||
struct fast_classifier *sc = &__sc;
|
||||
|
||||
spin_lock_bh(&sc->lock);
|
||||
sc->exceptions[except]++;
|
||||
@ -202,7 +217,7 @@ static inline void fast_classifier_incr_exceptions(fast_classifier_exception_t e
|
||||
*
|
||||
* Returns 1 if the packet is forwarded or 0 if it isn't.
|
||||
*/
|
||||
static int fast_classifier_recv(struct sk_buff *skb)
|
||||
int fast_classifier_recv(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct net_device *master_dev = NULL;
|
||||
@ -224,22 +239,12 @@ static int fast_classifier_recv(struct sk_buff *skb)
|
||||
(dev->priv_flags & IFF_BRIDGE_PORT)) {
|
||||
master_dev = sfe_dev_get_master(dev);
|
||||
if (!master_dev) {
|
||||
DEBUG_WARN("master dev is NULL %s\n");
|
||||
DEBUG_WARN("master dev is NULL %s\n", dev->name);
|
||||
goto rx_exit;
|
||||
}
|
||||
dev = master_dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
/*
|
||||
* If ingress Qdisc configured, and packet not processed by ingress Qdisc yet
|
||||
* We cannot accelerate this packet.
|
||||
*/
|
||||
if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) {
|
||||
goto rx_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We're only interested in IPv4 and IPv6 packets.
|
||||
*/
|
||||
@ -311,7 +316,7 @@ rx_exit:
|
||||
* structure, obtain the hardware address. This means this function also
|
||||
* works if the neighbours are routers too.
|
||||
*/
|
||||
static bool fast_classifier_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, bool is_v4)
|
||||
static bool fast_classifier_find_dev_and_mac_addr(struct sk_buff *skb, sfe_ip_addr_t *addr, struct net_device **dev, u8 *mac_addr, bool is_v4)
|
||||
{
|
||||
struct neighbour *neigh;
|
||||
struct rtable *rt;
|
||||
@ -319,12 +324,21 @@ static bool fast_classifier_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct ne
|
||||
struct dst_entry *dst;
|
||||
struct net_device *mac_dev;
|
||||
|
||||
/*
|
||||
* If we have skb provided, use it as the original code is unable
|
||||
* to lookup routes that are policy routed.
|
||||
*/
|
||||
if (unlikely(skb)) {
|
||||
dst = skb_dst(skb);
|
||||
goto skip_dst_lookup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up the rtable entry for the IP address then get the hardware
|
||||
* address from its neighbour structure. This means this works when the
|
||||
* neighbours are routers too.
|
||||
*/
|
||||
if (is_v4) {
|
||||
if (likely(is_v4)) {
|
||||
rt = ip_route_output(&init_net, addr->ip, 0, 0, 0);
|
||||
if (unlikely(IS_ERR(rt))) {
|
||||
goto ret_fail;
|
||||
@ -332,7 +346,11 @@ static bool fast_classifier_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct ne
|
||||
|
||||
dst = (struct dst_entry *)rt;
|
||||
} else {
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
|
||||
rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0);
|
||||
#else
|
||||
rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0);
|
||||
#endif /*KERNEL_VERSION(4, 17, 0)*/
|
||||
if (!rt6) {
|
||||
goto ret_fail;
|
||||
}
|
||||
@ -340,18 +358,23 @@ static bool fast_classifier_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct ne
|
||||
dst = (struct dst_entry *)rt6;
|
||||
}
|
||||
|
||||
skip_dst_lookup:
|
||||
rcu_read_lock();
|
||||
neigh = dst_neigh_lookup(dst, addr);
|
||||
neigh = sfe_dst_get_neighbour(dst, addr);
|
||||
if (unlikely(!neigh)) {
|
||||
rcu_read_unlock();
|
||||
dst_release(dst);
|
||||
if (likely(!skb))
|
||||
dst_release(dst);
|
||||
|
||||
goto ret_fail;
|
||||
}
|
||||
|
||||
if (unlikely(!(neigh->nud_state & NUD_VALID))) {
|
||||
rcu_read_unlock();
|
||||
neigh_release(neigh);
|
||||
dst_release(dst);
|
||||
if (likely(!skb))
|
||||
dst_release(dst);
|
||||
|
||||
goto ret_fail;
|
||||
}
|
||||
|
||||
@ -359,7 +382,9 @@ static bool fast_classifier_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct ne
|
||||
if (!mac_dev) {
|
||||
rcu_read_unlock();
|
||||
neigh_release(neigh);
|
||||
dst_release(dst);
|
||||
if (likely(!skb))
|
||||
dst_release(dst);
|
||||
|
||||
goto ret_fail;
|
||||
}
|
||||
|
||||
@ -369,12 +394,18 @@ static bool fast_classifier_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct ne
|
||||
*dev = mac_dev;
|
||||
rcu_read_unlock();
|
||||
neigh_release(neigh);
|
||||
dst_release(dst);
|
||||
if (likely(!skb))
|
||||
dst_release(dst);
|
||||
|
||||
return true;
|
||||
|
||||
ret_fail:
|
||||
DEBUG_TRACE("failed to find MAC address for IP: %pIS\n", addr);
|
||||
if (is_v4) {
|
||||
DEBUG_TRACE("failed to find MAC address for IP: %pI4\n", addr);
|
||||
|
||||
} else {
|
||||
DEBUG_TRACE("failed to find MAC address for IP: %pI6\n", addr);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -439,16 +470,16 @@ static int fast_classifier_update_protocol(struct sfe_connection_create *p_sic,
|
||||
* state can not be SYN_SENT, SYN_RECV because connection is assured
|
||||
* Not managed states: FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE.
|
||||
*/
|
||||
spin_lock_bh(&ct->lock);
|
||||
spin_lock(&ct->lock);
|
||||
if (ct->proto.tcp.state != TCP_CONNTRACK_ESTABLISHED) {
|
||||
spin_unlock_bh(&ct->lock);
|
||||
spin_unlock(&ct->lock);
|
||||
fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_TCP_NOT_ESTABLISHED);
|
||||
DEBUG_TRACE("connection in termination state: %#x, s: %pI4:%u, d: %pI4:%u\n",
|
||||
ct->proto.tcp.state, &p_sic->src_ip, ntohs(p_sic->src_port),
|
||||
&p_sic->dest_ip, ntohs(p_sic->dest_port));
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_bh(&ct->lock);
|
||||
spin_unlock(&ct->lock);
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
@ -511,12 +542,17 @@ static void fast_classifier_send_genl_msg(int msg, struct fast_classifier_tuple
|
||||
return;
|
||||
}
|
||||
|
||||
genlmsg_end(skb, msg_head);
|
||||
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19 , 0))
|
||||
rc = genlmsg_end(skb, msg_head);
|
||||
if (rc < 0) {
|
||||
genlmsg_cancel(skb, msg_head);
|
||||
nlmsg_free(skb);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
genlmsg_end(skb, msg_head);
|
||||
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
|
||||
rc = genlmsg_multicast(&fast_classifier_gnl_family, skb, 0, 0, GFP_ATOMIC);
|
||||
@ -525,14 +561,18 @@ static void fast_classifier_send_genl_msg(int msg, struct fast_classifier_tuple
|
||||
#endif
|
||||
switch (msg) {
|
||||
case FAST_CLASSIFIER_C_OFFLOADED:
|
||||
atomic_inc(&offloaded_msgs);
|
||||
if (rc != 0)
|
||||
if (rc == 0) {
|
||||
atomic_inc(&offloaded_msgs);
|
||||
} else {
|
||||
atomic_inc(&offloaded_fail_msgs);
|
||||
}
|
||||
break;
|
||||
case FAST_CLASSIFIER_C_DONE:
|
||||
atomic_inc(&done_msgs);
|
||||
if (rc != 0)
|
||||
if (rc == 0) {
|
||||
atomic_inc(&done_msgs);
|
||||
} else {
|
||||
atomic_inc(&done_fail_msgs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG_ERROR("fast-classifer: Unknown message type sent!\n");
|
||||
@ -540,7 +580,11 @@ static void fast_classifier_send_genl_msg(int msg, struct fast_classifier_tuple
|
||||
}
|
||||
|
||||
DEBUG_TRACE("Notify NL message %d ", msg);
|
||||
DEBUG_TRACE("sip=%pIS dip=%pIS ", &fc_msg->src_saddr, &fc_msg->dst_saddr);
|
||||
if (fc_msg->ethertype == AF_INET) {
|
||||
DEBUG_TRACE("sip=%pI4 dip=%pI4 ", &fc_msg->src_saddr, &fc_msg->dst_saddr);
|
||||
} else {
|
||||
DEBUG_TRACE("sip=%pI6 dip=%pI6 ", &fc_msg->src_saddr, &fc_msg->dst_saddr);
|
||||
}
|
||||
DEBUG_TRACE("protocol=%d sport=%d dport=%d smac=%pM dmac=%pM\n",
|
||||
fc_msg->proto, fc_msg->sport, fc_msg->dport, fc_msg->smac, fc_msg->dmac);
|
||||
}
|
||||
@ -558,10 +602,13 @@ fast_classifier_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr,
|
||||
struct sfe_connection_create *p_sic;
|
||||
struct sfe_connection *conn;
|
||||
u32 key;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
||||
struct hlist_node *node;
|
||||
#endif
|
||||
|
||||
key = fc_conn_hash(saddr, daddr, sport, dport, is_v4);
|
||||
|
||||
sfe_hash_for_each_possible(fc_conn_ht, conn, hl, key) {
|
||||
sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) {
|
||||
if (conn->is_v4 != is_v4) {
|
||||
continue;
|
||||
}
|
||||
@ -595,10 +642,13 @@ fast_classifier_sb_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr,
|
||||
struct sfe_connection_create *p_sic;
|
||||
struct sfe_connection *conn;
|
||||
u32 key;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
||||
struct hlist_node *node;
|
||||
#endif
|
||||
|
||||
key = fc_conn_hash(saddr, daddr, sport, dport, is_v4);
|
||||
|
||||
sfe_hash_for_each_possible(fc_conn_ht, conn, hl, key) {
|
||||
sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) {
|
||||
if (conn->is_v4 != is_v4) {
|
||||
continue;
|
||||
}
|
||||
@ -619,7 +669,7 @@ fast_classifier_sb_find_conn(sfe_ip_addr_t *saddr, sfe_ip_addr_t *daddr,
|
||||
*/
|
||||
key = fc_conn_hash(daddr, saddr, dport, sport, is_v4);
|
||||
|
||||
sfe_hash_for_each_possible(fc_conn_ht, conn, hl, key) {
|
||||
sfe_hash_for_each_possible(fc_conn_ht, conn, node, hl, key) {
|
||||
if (conn->is_v4 != is_v4) {
|
||||
continue;
|
||||
}
|
||||
@ -667,8 +717,13 @@ fast_classifier_add_conn(struct sfe_connection *conn)
|
||||
|
||||
DEBUG_TRACE(" -> adding item to sfe_connections, new size: %d\n", sfe_connections_size);
|
||||
|
||||
DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pIS dst_ip: %pIS, src_port: %d, dst_port: %d\n",
|
||||
key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port);
|
||||
if (conn->is_v4) {
|
||||
DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n",
|
||||
key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port);
|
||||
} else {
|
||||
DEBUG_TRACE("new offloadable: key: %u proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n",
|
||||
key, sic->protocol, &(sic->src_ip), &(sic->dest_ip), sic->src_port, sic->dest_port);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
@ -687,15 +742,27 @@ fast_classifier_offload_genl_msg(struct sk_buff *skb, struct genl_info *info)
|
||||
na = info->attrs[FAST_CLASSIFIER_A_TUPLE];
|
||||
fc_msg = nla_data(na);
|
||||
|
||||
DEBUG_TRACE("want to offload: %d-%d, %pIS, %pIS, %d, %d SMAC=%pM DMAC=%pM\n",
|
||||
fc_msg->ethertype,
|
||||
fc_msg->proto,
|
||||
&fc_msg->src_saddr,
|
||||
&fc_msg->dst_saddr,
|
||||
fc_msg->sport,
|
||||
fc_msg->dport,
|
||||
fc_msg->smac,
|
||||
fc_msg->dmac);
|
||||
if (fc_msg->ethertype == AF_INET) {
|
||||
DEBUG_TRACE("want to offload: %d-%d, %pI4, %pI4, %d, %d SMAC=%pM DMAC=%pM\n",
|
||||
fc_msg->ethertype,
|
||||
fc_msg->proto,
|
||||
&fc_msg->src_saddr,
|
||||
&fc_msg->dst_saddr,
|
||||
fc_msg->sport,
|
||||
fc_msg->dport,
|
||||
fc_msg->smac,
|
||||
fc_msg->dmac);
|
||||
} else {
|
||||
DEBUG_TRACE("want to offload: %d-%d, %pI6, %pI6, %d, %d SMAC=%pM DMAC=%pM\n",
|
||||
fc_msg->ethertype,
|
||||
fc_msg->proto,
|
||||
&fc_msg->src_saddr,
|
||||
&fc_msg->dst_saddr,
|
||||
fc_msg->sport,
|
||||
fc_msg->dport,
|
||||
fc_msg->smac,
|
||||
fc_msg->dmac);
|
||||
}
|
||||
|
||||
spin_lock_bh(&sfe_connections_lock);
|
||||
conn = fast_classifier_sb_find_conn((sfe_ip_addr_t *)&fc_msg->src_saddr,
|
||||
@ -747,12 +814,14 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
struct net_device *dev;
|
||||
struct net_device *src_dev;
|
||||
struct net_device *dest_dev;
|
||||
struct net_device *src_dev_tmp;
|
||||
struct net_device *dest_dev_tmp;
|
||||
struct net_device *src_br_dev = NULL;
|
||||
struct net_device *dest_br_dev = NULL;
|
||||
struct nf_conntrack_tuple orig_tuple;
|
||||
struct nf_conntrack_tuple reply_tuple;
|
||||
struct sfe_connection *conn;
|
||||
SFE_NF_CONN_ACCT(acct);
|
||||
struct sk_buff *tmp_skb = NULL;
|
||||
|
||||
/*
|
||||
* Don't process broadcast or multicast packets.
|
||||
@ -790,6 +859,7 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
|
||||
/*
|
||||
* Don't process untracked connections.
|
||||
*/
|
||||
@ -798,6 +868,7 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
DEBUG_TRACE("untracked connection\n");
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
#endif /*KERNEL_VERSION(4, 12, 0)*/
|
||||
|
||||
/*
|
||||
* Unconfirmed connection may be dropped by Linux at the final step,
|
||||
@ -818,21 +889,6 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the acceleration of a flow could be rejected quickly.
|
||||
*/
|
||||
acct = nf_conn_acct_find(ct);
|
||||
if (acct) {
|
||||
long long packets = atomic64_read(&SFE_ACCT_COUNTER(acct)[CTINFO2DIR(ctinfo)].packets);
|
||||
if ((packets > 0xff) && (packets & 0xff)) {
|
||||
/*
|
||||
* Connection hits slow path at least 256 times, so it must be not able to accelerate.
|
||||
* But we also give it a chance to walk through ECM every 256 packets
|
||||
*/
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&sic, 0, sizeof(sic));
|
||||
|
||||
/*
|
||||
@ -850,7 +906,7 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
/*
|
||||
* Get addressing information, non-NAT first
|
||||
*/
|
||||
if (is_v4) {
|
||||
if (likely(is_v4)) {
|
||||
u32 dscp;
|
||||
|
||||
sic.src_ip.ip = (__be32)orig_tuple.src.u3.ip;
|
||||
@ -926,6 +982,21 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
sic.dest_port = orig_tuple.dst.u.udp.port;
|
||||
sic.src_port_xlate = reply_tuple.dst.u.udp.port;
|
||||
sic.dest_port_xlate = reply_tuple.src.u.udp.port;
|
||||
|
||||
/*
|
||||
* Somehow, SFE is not playing nice with IPSec traffic.
|
||||
* Do not accelerate for now.
|
||||
*/
|
||||
if (ntohs(sic.dest_port) == 4500 || ntohs(sic.dest_port) == 500) {
|
||||
if (likely(is_v4))
|
||||
DEBUG_TRACE("quarkysg:: IPsec bypass: %pI4:%d(%pI4:%d) to %pI4:%d(%pI4:%d)\n",
|
||||
&sic.src_ip.ip, ntohs(sic.src_port), &sic.src_ip_xlate.ip, ntohs(sic.src_port_xlate),
|
||||
&sic.dest_ip.ip, ntohs(sic.dest_port), &sic.dest_ip_xlate.ip, ntohs(sic.dest_port_xlate));
|
||||
else
|
||||
DEBUG_TRACE("quarkysg:: IPsec bypass: %pI6:%d to %pI6:%d\n",
|
||||
&sic.src_ip.ip6, ntohs(sic.src_port), &sic.dest_ip.ip6, ntohs(sic.dest_port));
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -948,8 +1019,13 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
sic.flags |= SFE_CREATE_FLAG_REMARK_PRIORITY;
|
||||
}
|
||||
|
||||
DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pIS dst_ip: %pIS, src_port: %d, dst_port: %d\n",
|
||||
sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port);
|
||||
if (is_v4) {
|
||||
DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n",
|
||||
sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port);
|
||||
} else {
|
||||
DEBUG_TRACE("POST_ROUTE: checking new connection: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n",
|
||||
sic.protocol, &sic.src_ip, &sic.dest_ip, sic.src_port, sic.dest_port);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we already have this connection in our list, skip it
|
||||
@ -1018,32 +1094,35 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
* Get the net device and MAC addresses that correspond to the various source and
|
||||
* destination host addresses.
|
||||
*/
|
||||
if (!fast_classifier_find_dev_and_mac_addr(&sic.src_ip, &src_dev, sic.src_mac, is_v4)) {
|
||||
if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) {
|
||||
fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_DEV);
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
src_dev = src_dev_tmp;
|
||||
|
||||
if (!fast_classifier_find_dev_and_mac_addr(&sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) {
|
||||
if (!fast_classifier_find_dev_and_mac_addr(NULL, &sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) {
|
||||
fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_SRC_XLATE_DEV);
|
||||
goto done1;
|
||||
}
|
||||
|
||||
dev_put(dev);
|
||||
|
||||
if (!fast_classifier_find_dev_and_mac_addr(&sic.dest_ip, &dev, sic.dest_mac, is_v4)) {
|
||||
if (unlikely(!is_v4))
|
||||
tmp_skb = skb;
|
||||
|
||||
if (!fast_classifier_find_dev_and_mac_addr(tmp_skb, &sic.dest_ip, &dev, sic.dest_mac, is_v4)) {
|
||||
fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_DEV);
|
||||
goto done1;
|
||||
}
|
||||
|
||||
dev_put(dev);
|
||||
|
||||
if (!fast_classifier_find_dev_and_mac_addr(&sic.dest_ip_xlate, &dest_dev, sic.dest_mac_xlate, is_v4)) {
|
||||
if (!fast_classifier_find_dev_and_mac_addr(skb, &sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) {
|
||||
fast_classifier_incr_exceptions(FAST_CL_EXCEPTION_NO_DEST_XLATE_DEV);
|
||||
goto done1;
|
||||
}
|
||||
dest_dev = dest_dev_tmp;
|
||||
|
||||
/*
|
||||
* Our devices may actually be part of a bridge interface. If that's
|
||||
* Our devices may actually be part of a bridge interface. If that's
|
||||
* the case then find the bridge interface instead.
|
||||
*/
|
||||
if (src_dev->priv_flags & IFF_BRIDGE_PORT) {
|
||||
@ -1053,7 +1132,6 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
DEBUG_TRACE("no bridge found for: %s\n", src_dev->name);
|
||||
goto done2;
|
||||
}
|
||||
|
||||
src_dev = src_br_dev;
|
||||
}
|
||||
|
||||
@ -1064,7 +1142,6 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name);
|
||||
goto done3;
|
||||
}
|
||||
|
||||
dest_dev = dest_br_dev;
|
||||
}
|
||||
|
||||
@ -1082,7 +1159,7 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
|
||||
if (!conn) {
|
||||
printk(KERN_CRIT "ERROR: no memory for sfe\n");
|
||||
goto done3;
|
||||
goto done4;
|
||||
}
|
||||
conn->hits = 0;
|
||||
conn->offload_permit = 0;
|
||||
@ -1096,7 +1173,7 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
if (!p_sic) {
|
||||
printk(KERN_CRIT "ERROR: no memory for sfe\n");
|
||||
kfree(conn);
|
||||
goto done3;
|
||||
goto done4;
|
||||
}
|
||||
|
||||
memcpy(p_sic, &sic, sizeof(sic));
|
||||
@ -1111,20 +1188,18 @@ static unsigned int fast_classifier_post_routing(struct sk_buff *skb, bool is_v4
|
||||
/*
|
||||
* If we had bridge ports then release them too.
|
||||
*/
|
||||
done4:
|
||||
if (dest_br_dev) {
|
||||
dev_put(dest_br_dev);
|
||||
}
|
||||
|
||||
done3:
|
||||
if (src_br_dev) {
|
||||
dev_put(src_br_dev);
|
||||
}
|
||||
|
||||
done2:
|
||||
dev_put(dest_dev);
|
||||
|
||||
dev_put(dest_dev_tmp);
|
||||
done1:
|
||||
dev_put(src_dev);
|
||||
dev_put(src_dev_tmp);
|
||||
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
@ -1198,6 +1273,7 @@ static int fast_classifier_conntrack_event(unsigned int events, struct nf_ct_eve
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
|
||||
/*
|
||||
* If this is an untracked connection then we can't have any state either.
|
||||
*/
|
||||
@ -1205,6 +1281,7 @@ static int fast_classifier_conntrack_event(unsigned int events, struct nf_ct_eve
|
||||
DEBUG_TRACE("ignoring untracked conn\n");
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
#endif /*KERNEL_VERSION(4, 12, 0)*/
|
||||
|
||||
orig_tuple = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
|
||||
sid.protocol = (s32)orig_tuple.dst.protonum;
|
||||
@ -1267,8 +1344,13 @@ static int fast_classifier_conntrack_event(unsigned int events, struct nf_ct_eve
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pIS dst_ip: %pIS, src_port: %d, dst_port: %d\n",
|
||||
sid.protocol, &sid.src_ip, &sid.dest_ip, sid.src_port, sid.dest_port);
|
||||
if (is_v4) {
|
||||
DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI4 dst_ip: %pI4, src_port: %d, dst_port: %d\n",
|
||||
sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port));
|
||||
} else {
|
||||
DEBUG_TRACE("Try to clean up: proto: %d src_ip: %pI6 dst_ip: %pI6, src_port: %d, dst_port: %d\n",
|
||||
sid.protocol, &sid.src_ip, &sid.dest_ip, ntohs(sid.src_port), ntohs(sid.dest_port));
|
||||
}
|
||||
|
||||
spin_lock_bh(&sfe_connections_lock);
|
||||
|
||||
@ -1416,7 +1498,9 @@ static void fast_classifier_sync_rule(struct sfe_connection_sync *sis)
|
||||
}
|
||||
|
||||
ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
|
||||
NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct);
|
||||
#endif /*KERNEL_VERSION(4, 9, 0)*/
|
||||
|
||||
/*
|
||||
* Only update if this is not a fixed timeout
|
||||
@ -1427,7 +1511,7 @@ static void fast_classifier_sync_rule(struct sfe_connection_sync *sis)
|
||||
ct->timeout += sis->delta_jiffies;
|
||||
#else
|
||||
ct->timeout.expires += sis->delta_jiffies;
|
||||
#endif
|
||||
#endif /*KERNEL_VERSION(4, 9, 0)*/
|
||||
spin_unlock_bh(&ct->lock);
|
||||
}
|
||||
|
||||
@ -1456,7 +1540,7 @@ static void fast_classifier_sync_rule(struct sfe_connection_sync *sis)
|
||||
if (ct->proto.tcp.seen[1].td_maxwin < sis->dest_td_max_window) {
|
||||
ct->proto.tcp.seen[1].td_maxwin = sis->dest_td_max_window;
|
||||
}
|
||||
if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) {
|
||||
if ((s32)(ct->proto.tcp.seen[1].td_end - sis->dest_td_end) < 0) {
|
||||
ct->proto.tcp.seen[1].td_end = sis->dest_td_end;
|
||||
}
|
||||
if ((s32)(ct->proto.tcp.seen[1].td_maxend - sis->dest_td_max_end) < 0) {
|
||||
@ -1464,42 +1548,6 @@ static void fast_classifier_sync_rule(struct sfe_connection_sync *sis)
|
||||
}
|
||||
spin_unlock_bh(&ct->lock);
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
/*
|
||||
* In Linux connection track, UDP flow has two timeout values:
|
||||
* /proc/sys/net/netfilter/nf_conntrack_udp_timeout:
|
||||
* this is for uni-direction UDP flow, normally its value is 60 seconds
|
||||
* /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream:
|
||||
* this is for bi-direction UDP flow, normally its value is 180 seconds
|
||||
*
|
||||
* Linux will update timer of UDP flow to stream timeout once it seen packets
|
||||
* in reply direction. But if flow is accelerated by NSS or SFE, Linux won't
|
||||
* see any packets. So we have to do the same thing in our stats sync message.
|
||||
*/
|
||||
if (!test_bit(IPS_ASSURED_BIT, &ct->status) && acct) {
|
||||
u_int64_t reply_pkts = atomic64_read(&SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets);
|
||||
|
||||
if (reply_pkts != 0) {
|
||||
struct nf_conntrack_l4proto *l4proto;
|
||||
unsigned int *timeouts;
|
||||
|
||||
set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
|
||||
set_bit(IPS_ASSURED_BIT, &ct->status);
|
||||
|
||||
l4proto = __nf_ct_l4proto_find((sis->is_v6 ? AF_INET6 : AF_INET), IPPROTO_UDP);
|
||||
timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto);
|
||||
|
||||
spin_lock_bh(&ct->lock);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||
ct->timeout = nfct_time_stamp + timeouts[UDP_CT_REPLIED];
|
||||
#else
|
||||
ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED];
|
||||
#endif
|
||||
spin_unlock_bh(&ct->lock);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1590,10 +1638,13 @@ static ssize_t fast_classifier_get_debug_info(struct device *dev,
|
||||
size_t len = 0;
|
||||
struct sfe_connection *conn;
|
||||
u32 i;
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
|
||||
struct hlist_node *node;
|
||||
#endif
|
||||
|
||||
spin_lock_bh(&sfe_connections_lock);
|
||||
len += scnprintf(buf, PAGE_SIZE - len, "size=%d offload=%d offload_no_match=%d"
|
||||
" offloaded=%d done=%d offl_dbg_msg_fail=%d done_dbg_msg_fail=%d\n",
|
||||
" offloaded=%d done=%d offloaded_fail=%d done_fail=%d\n",
|
||||
sfe_connections_size,
|
||||
atomic_read(&offload_msgs),
|
||||
atomic_read(&offload_no_match_msgs),
|
||||
@ -1601,16 +1652,16 @@ static ssize_t fast_classifier_get_debug_info(struct device *dev,
|
||||
atomic_read(&done_msgs),
|
||||
atomic_read(&offloaded_fail_msgs),
|
||||
atomic_read(&done_fail_msgs));
|
||||
sfe_hash_for_each(fc_conn_ht, i, conn, hl) {
|
||||
sfe_hash_for_each(fc_conn_ht, i, node, conn, hl) {
|
||||
len += scnprintf(buf + len, PAGE_SIZE - len,
|
||||
(conn->is_v4 ? "o=%d, p=%d [%pM]:%pI4:%u %pI4:%u:[%pM] m=%08x h=%d\n" : "o=%d, p=%d [%pM]:%pI6:%u %pI6:%u:[%pM] m=%08x h=%d\n"),
|
||||
conn->offloaded,
|
||||
conn->sic->protocol,
|
||||
conn->sic->src_mac,
|
||||
&conn->sic->src_ip,
|
||||
conn->sic->src_port,
|
||||
ntohs(conn->sic->src_port),
|
||||
&conn->sic->dest_ip,
|
||||
conn->sic->dest_port,
|
||||
ntohs(conn->sic->dest_port),
|
||||
conn->sic->dest_mac_xlate,
|
||||
conn->sic->mark,
|
||||
conn->hits);
|
||||
@ -1658,7 +1709,7 @@ static ssize_t fast_classifier_get_exceptions(struct device *dev,
|
||||
char *buf)
|
||||
{
|
||||
int idx, len;
|
||||
struct fast_classifier *sc = &__fsc;
|
||||
struct fast_classifier *sc = &__sc;
|
||||
|
||||
spin_lock_bh(&sc->lock);
|
||||
for (len = 0, idx = 0; idx < FAST_CL_EXCEPTION_MAX; idx++) {
|
||||
@ -1674,23 +1725,24 @@ static ssize_t fast_classifier_get_exceptions(struct device *dev,
|
||||
/*
|
||||
* sysfs attributes.
|
||||
*/
|
||||
static const struct device_attribute fast_classifier_attrs[] = {
|
||||
__ATTR(offload_at_pkts, S_IWUSR | S_IRUGO, fast_classifier_get_offload_at_pkts, fast_classifier_set_offload_at_pkts),
|
||||
__ATTR(debug_info, S_IRUGO, fast_classifier_get_debug_info, NULL),
|
||||
__ATTR(skip_to_bridge_ingress, S_IWUSR | S_IRUGO, fast_classifier_get_skip_bridge_ingress, fast_classifier_set_skip_bridge_ingress),
|
||||
__ATTR(exceptions, S_IRUGO, fast_classifier_get_exceptions, NULL),
|
||||
};
|
||||
static const struct device_attribute fast_classifier_offload_at_pkts_attr =
|
||||
__ATTR(offload_at_pkts, S_IWUSR | S_IRUGO, fast_classifier_get_offload_at_pkts, fast_classifier_set_offload_at_pkts);
|
||||
static const struct device_attribute fast_classifier_debug_info_attr =
|
||||
__ATTR(debug_info, S_IRUGO, fast_classifier_get_debug_info, NULL);
|
||||
static const struct device_attribute fast_classifier_skip_bridge_ingress =
|
||||
__ATTR(skip_to_bridge_ingress, S_IWUSR | S_IRUGO, fast_classifier_get_skip_bridge_ingress, fast_classifier_set_skip_bridge_ingress);
|
||||
static const struct device_attribute fast_classifier_exceptions_attr =
|
||||
__ATTR(exceptions, S_IRUGO, fast_classifier_get_exceptions, NULL);
|
||||
|
||||
/*
|
||||
* fast_classifier_init()
|
||||
*/
|
||||
static int __init fast_classifier_init(void)
|
||||
{
|
||||
struct fast_classifier *sc = &__fsc;
|
||||
struct fast_classifier *sc = &__sc;
|
||||
int result = -1;
|
||||
size_t i, j;
|
||||
|
||||
printk(KERN_ALERT "fast-classifier: starting up\n");
|
||||
printk(KERN_ALERT "fast-classifier (PBR safe v2.1.4a): starting up\n");
|
||||
DEBUG_INFO("SFE CM init\n");
|
||||
|
||||
hash_init(fc_conn_ht);
|
||||
@ -1704,13 +1756,34 @@ static int __init fast_classifier_init(void)
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fast_classifier_attrs); i++) {
|
||||
result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_attrs[i].attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register %s : %d\n",
|
||||
fast_classifier_attrs[i].attr.name, result);
|
||||
goto exit2;
|
||||
}
|
||||
result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register offload at pkgs: %d\n", result);
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register debug dev: %d\n", result);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr);
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register skip bridge on ingress: %d\n", result);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr);
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
result = sysfs_create_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register exceptions file: %d\n", result);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr);
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
sc->dev_notifier.notifier_call = fast_classifier_device_event;
|
||||
@ -1728,7 +1801,7 @@ static int __init fast_classifier_init(void)
|
||||
/*
|
||||
* Register our netfilter hooks.
|
||||
*/
|
||||
result = nf_register_hooks(fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));
|
||||
result = nf_register_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));
|
||||
if (result < 0) {
|
||||
DEBUG_ERROR("can't register nf post routing hook: %d\n", result);
|
||||
goto exit3;
|
||||
@ -1737,22 +1810,21 @@ static int __init fast_classifier_init(void)
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
/*
|
||||
* Register a notifier hook to get fast notifications of expired connections.
|
||||
* Note: In CONFIG_NF_CONNTRACK_CHAIN_EVENTS enabled case, nf_conntrack_register_notifier()
|
||||
* function always returns 0.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
(void)nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier);
|
||||
#else
|
||||
result = nf_conntrack_register_notifier(&init_net, &fast_classifier_conntrack_notifier);
|
||||
if (result < 0) {
|
||||
DEBUG_ERROR("can't register nf notifier hook: %d\n", result);
|
||||
goto exit4;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
|
||||
result = genl_register_family(&fast_classifier_gnl_family);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register genl family: %d\n", result);
|
||||
goto exit5;
|
||||
}
|
||||
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
|
||||
result = genl_register_family_with_ops_groups(&fast_classifier_gnl_family,
|
||||
fast_classifier_gnl_ops,
|
||||
fast_classifier_genl_mcgrp);
|
||||
@ -1788,8 +1860,8 @@ static int __init fast_classifier_init(void)
|
||||
/*
|
||||
* Hook the receive path in the network stack.
|
||||
*/
|
||||
BUG_ON(fast_nat_recv);
|
||||
RCU_INIT_POINTER(fast_nat_recv, fast_classifier_recv);
|
||||
BUG_ON(athrs_fast_nat_recv);
|
||||
RCU_INIT_POINTER(athrs_fast_nat_recv, fast_classifier_recv);
|
||||
|
||||
/*
|
||||
* Hook the shortcut sync callback.
|
||||
@ -1809,17 +1881,18 @@ exit5:
|
||||
|
||||
exit4:
|
||||
#endif
|
||||
nf_unregister_hooks(fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));
|
||||
nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));
|
||||
|
||||
exit3:
|
||||
unregister_inetaddr_notifier(&sc->inet_notifier);
|
||||
unregister_inet6addr_notifier(&sc->inet6_notifier);
|
||||
unregister_netdevice_notifier(&sc->dev_notifier);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_offload_at_pkts_attr.attr);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_debug_info_attr.attr);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_skip_bridge_ingress.attr);
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_exceptions_attr.attr);
|
||||
|
||||
exit2:
|
||||
for (j = 0; j < i; j++) {
|
||||
sysfs_remove_file(sc->sys_fast_classifier, &fast_classifier_attrs[j].attr);
|
||||
}
|
||||
kobject_put(sc->sys_fast_classifier);
|
||||
|
||||
exit1:
|
||||
@ -1831,7 +1904,7 @@ exit1:
|
||||
*/
|
||||
static void __exit fast_classifier_exit(void)
|
||||
{
|
||||
struct fast_classifier *sc = &__fsc;
|
||||
struct fast_classifier *sc = &__sc;
|
||||
int result = -1;
|
||||
|
||||
DEBUG_INFO("SFE CM exit\n");
|
||||
@ -1846,7 +1919,7 @@ static void __exit fast_classifier_exit(void)
|
||||
/*
|
||||
* Unregister our receive callback.
|
||||
*/
|
||||
RCU_INIT_POINTER(fast_nat_recv, NULL);
|
||||
RCU_INIT_POINTER(athrs_fast_nat_recv, NULL);
|
||||
|
||||
/*
|
||||
* Wait for all callbacks to complete.
|
||||
@ -1868,14 +1941,14 @@ static void __exit fast_classifier_exit(void)
|
||||
|
||||
result = genl_unregister_family(&fast_classifier_gnl_family);
|
||||
if (result != 0) {
|
||||
printk(KERN_CRIT "Unable to unreigster genl_family\n");
|
||||
printk(KERN_CRIT "Unable to unregister genl_family\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
nf_conntrack_unregister_notifier(&init_net, &fast_classifier_conntrack_notifier);
|
||||
|
||||
#endif
|
||||
nf_unregister_hooks(fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));
|
||||
nf_unregister_net_hooks(&init_net, fast_classifier_ops_post_routing, ARRAY_SIZE(fast_classifier_ops_post_routing));
|
||||
|
||||
unregister_inet6addr_notifier(&sc->inet6_notifier);
|
||||
unregister_inetaddr_notifier(&sc->inet_notifier);
|
||||
@ -18,7 +18,7 @@
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "fast-classifier.h"
|
||||
#include <fast-classifier.h>
|
||||
|
||||
static struct nl_sock *sock;
|
||||
static struct nl_sock *sock_event;
|
||||
@ -6,10 +6,10 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for Flow Offload
|
||||
LUCI_DEPENDS:=+kmod-ipt-offload +pdnsd-alt +kmod-tcp-bbr @!LINUX_4_9
|
||||
LUCI_DEPENDS:=+kmod-ipt-offload +pdnsd-alt +kmod-tcp-bbr @LINUX_5_4
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=15
|
||||
PKG_RELEASE:=19
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@ -6,6 +6,6 @@ config flow
|
||||
option dns '0'
|
||||
option dnscache_enable '1'
|
||||
option dns_server '114.114.114.114,114.114.115.115,223.5.5.5,223.6.6.6,180.76.76.76,119.29.29.29,119.28.28.28,1.2.4.8,210.2.4.8'
|
||||
option ipv6dns_server '240c::6666,240c::6644,2400:da00::6666,2001:da8::666'
|
||||
option ipv6dns_server '240c::6666,240c::6644,2001:da8::666,2001:da8:202:10::36,2001:da8:8000:1:202:120:2:100'
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ USE_PROCD=1
|
||||
|
||||
DNSMASQ_RESTART=N
|
||||
DNS_SERVER="114.114.114.114,114.114.115.115,223.5.5.5,223.6.6.6,180.76.76.76,119.29.29.29,119.28.28.28,1.2.4.8,210.2.4.8"
|
||||
IPV6DNS_SERVER="2001:4860:4860::8888,2001:4860:4860::8844,2001:2001::1111,2001:2001::1001,2400:da00::6666,240C::6666,240C::6644"
|
||||
IPV6DNS_SERVER="240c::6666,240c::6644,2001:da8::666,2001:da8:202:10::36,2001:da8:8000:1:202:120:2:100"
|
||||
|
||||
start_pdnsd() {
|
||||
DNS_SERVER=$(uci get flowoffload.@flow[0].dns_server 2>/dev/null)
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
LUCI_TITLE:=LuCI support for Turbo ACC (SFE)
|
||||
LUCI_DEPENDS:=+kmod-fast-classifier +pdnsd-alt +kmod-tcp-bbr @LINUX_4_9
|
||||
LUCI_DEPENDS:=+kmod-fast-classifier +pdnsd-alt +kmod-tcp-bbr
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_VERSION:=1.0
|
||||
PKG_RELEASE:=38
|
||||
PKG_RELEASE:=13
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-unblockmusic
|
||||
PKG_VERSION:=2.3.5
|
||||
PKG_RELEASE:=7
|
||||
PKG_RELEASE:=8
|
||||
|
||||
PKG_CONFIG_DEPENDS := \
|
||||
CONFIG_UnblockNeteaseMusic_Go \
|
||||
|
||||
@ -184,9 +184,8 @@ start()
|
||||
add_cron
|
||||
echo "$(date -R) # UnblockNeteaseMusic Nodejs Version (http:5200, https:5201)" >>/tmp/unblockmusic.log
|
||||
elif [ "$APPTYPE" == "go" ]; then
|
||||
UnblockNeteaseMusic -p 5200 -sp 5202 -m 0 -c /usr/share/UnblockNeteaseMusicGo/server.crt -k /usr/share/UnblockNeteaseMusicGo/server.key -m 0 >>/tmp/unblockmusic.log 2>&1 &
|
||||
UnblockNeteaseMusic -p 5200 -sp 5201 -m 0 -c /usr/share/UnblockNeteaseMusicGo/server.crt -k /usr/share/UnblockNeteaseMusicGo/server.key -m 0 -e >>/tmp/unblockmusic.log 2>&1 &
|
||||
echo "$(date -R) # UnblockNeteaseMusic Golang Version (http:5200, https:5201)" >>/tmp/unblockmusic.log
|
||||
UnblockNeteaseMusic -p 5203 -sp 5201 -m 0 -c /usr/share/UnblockNeteaseMusicGo/server.crt -k /usr/share/UnblockNeteaseMusicGo/server.key -m 0 -e >>/tmp/unblockmusic.log 2>&1 &
|
||||
else
|
||||
kill -9 $(busybox ps -w | grep 'sleep 60m' | grep -v grep | awk '{print $1}') >/dev/null 2>&1
|
||||
/usr/bin/UnblockNeteaseMusicCloud >/dev/null 2>&1 &
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
chmod 777 /sbin/mtkwifi
|
||||
chmod 0755 /sbin/mtkwifi
|
||||
START=15
|
||||
STOP=15
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=qBittorrent-Enhanced-Edition
|
||||
PKG_VERSION:=4.2.5.10
|
||||
PKG_VERSION:=4.2.5.12
|
||||
PKG_RELEASE=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-release-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/c0re100/qBittorrent-Enhanced-Edition/tar.gz/release-$(PKG_VERSION)?
|
||||
PKG_HASH:=d3c98f3beec064af5c95efa075fda2bb8aa5a9dec4219ff9bd003f27c8a24d36
|
||||
PKG_HASH:=1317cf11bc7f9cef418c177aee29d3a0d36c21cb7c06319d86bb49e5d3d8fa97
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/qBittorrent-Enhanced-Edition-release-$(PKG_VERSION)
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=shortcut-fe
|
||||
PKG_RELEASE:=9
|
||||
PKG_RELEASE:=1
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
@ -23,17 +23,27 @@ define KernelPackage/shortcut-fe
|
||||
SECTION:=kernel
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Network Support
|
||||
DEPENDS:=@IPV6 @LINUX_4_9
|
||||
DEPENDS:=
|
||||
TITLE:=Kernel driver for SFE
|
||||
FILES:=$(PKG_BUILD_DIR)/shortcut-fe.ko $(PKG_BUILD_DIR)/shortcut-fe-ipv6.ko
|
||||
KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y CONFIG_SHORTCUT_FE=y
|
||||
AUTOLOAD:=$(call AutoProbe,shortcut-fe shortcut-fe-ipv6)
|
||||
KCONFIG:=CONFIG_NF_CONNTRACK_EVENTS=y \
|
||||
CONFIG_NF_CONNTRACK_TIMEOUT=y \
|
||||
CONFIG_SHORTCUT_FE=y \
|
||||
CONFIG_XFRM=y
|
||||
AUTOLOAD:=$(call AutoLoad,09,shortcut-fe shortcut-fe-ipv6)
|
||||
endef
|
||||
|
||||
define KernelPackage/shortcut-fe/Description
|
||||
Shortcut is an in-Linux-kernel IP packet forwarding engine.
|
||||
endef
|
||||
|
||||
define KernelPackage/shortcut-fe/install
|
||||
$(INSTALL_DIR) $(1)/etc/init.d
|
||||
$(INSTALL_BIN) ./files/etc/init.d/shortcut-fe $(1)/etc/init.d
|
||||
$(INSTALL_DIR) $(1)/usr/bin
|
||||
$(INSTALL_BIN) ./files/usr/bin/sfe_dump $(1)/usr/bin
|
||||
endef
|
||||
|
||||
define KernelPackage/shortcut-fe-cm
|
||||
SECTION:=kernel
|
||||
CATEGORY:=Kernel modules
|
||||
@ -41,81 +51,31 @@ define KernelPackage/shortcut-fe-cm
|
||||
DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe
|
||||
TITLE:=Kernel driver for SFE
|
||||
FILES:=$(PKG_BUILD_DIR)/shortcut-fe-cm.ko
|
||||
KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y CONFIG_NF_CONNTRACK_MARK=y
|
||||
AUTOLOAD:=$(call AutoProbe,shortcut-fe-cm)
|
||||
KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y
|
||||
endef
|
||||
|
||||
define KernelPackage/shortcut-fe-cm/Description
|
||||
Simple connection manager for the Shortcut forwarding engine.
|
||||
endef
|
||||
|
||||
define KernelPackage/fast-classifier
|
||||
SECTION:=kernel
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Network Support
|
||||
DEPENDS:=+kmod-ipt-conntrack +kmod-shortcut-fe
|
||||
TITLE:=Kernel driver for FAST Classifier
|
||||
FILES:=$(PKG_BUILD_DIR)/fast-classifier.ko
|
||||
KCONFIG:=CONFIG_NF_CONNTRACK_CHAIN_EVENTS=y CONFIG_NF_CONNTRACK_MARK=y
|
||||
AUTOLOAD:=$(call AutoLoad,z,fast-classifier)
|
||||
PROVIDES:=$(PKG_NAME)
|
||||
endef
|
||||
|
||||
define KernelPackage/fast-classifier/description
|
||||
FAST Classifier connection manager for Shortcut forwarding engine.
|
||||
It talks to SFE to make decisions about offloading connections.
|
||||
endef
|
||||
|
||||
define Package/fast-classifier-example
|
||||
TITLE:=Example user space program for fast-classifier
|
||||
DEPENDS:=+libnl +kmod-fast-classifier
|
||||
endef
|
||||
|
||||
define Package/fast-classifier-example/description
|
||||
Example user space program that communicates with fast
|
||||
classifier kernel module
|
||||
endef
|
||||
|
||||
MAKE_OPTS:= \
|
||||
ARCH="$(LINUX_KARCH)" \
|
||||
CROSS_COMPILE="$(TARGET_CROSS)" \
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
EXTRA_CFLAGS="$(EXTRA_CFLAGS)"
|
||||
EXTRA_CFLAGS+=-DSFE_SUPPORT_IPV6
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) -C "$(LINUX_DIR)" \
|
||||
$(MAKE_OPTS) \
|
||||
+$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \
|
||||
$(KERNEL_MAKE_FLAGS) \
|
||||
$(PKG_MAKE_FLAGS) \
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
|
||||
SFE_SUPPORT_IPV6=1 \
|
||||
modules
|
||||
$(if $(CONFIG_PACKAGE_fast-classifier-example),$(Build/Compile/fast-classifier-example))
|
||||
endef
|
||||
|
||||
define Build/Compile/fast-classifier-example
|
||||
$(TARGET_CC) -o $(PKG_BUILD_DIR)/userspace_fast_classifier \
|
||||
-I $(PKG_BUILD_DIR) \
|
||||
-I$(STAGING_DIR)/usr/include/libnl \
|
||||
-I$(STAGING_DIR)/usr/include/libnl3 \
|
||||
-lnl-genl-3 -lnl-3 \
|
||||
$(PKG_BUILD_DIR)/nl_classifier_test.c
|
||||
endef
|
||||
|
||||
ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm)$(CONFIG_PACKAGE_kmod-fast-classifier),)
|
||||
ifneq ($(CONFIG_PACKAGE_kmod-shortcut-fe)$(CONFIG_PACKAGE_kmod-shortcut-fe-cm),)
|
||||
define Build/InstallDev
|
||||
$(INSTALL_DIR) $(1)/usr/include/shortcut-fe
|
||||
$(CP) -rf $(PKG_BUILD_DIR)/sfe.h $(1)/usr/include/shortcut-fe
|
||||
ifneq ($(CONFIG_PACKAGE_kmod-fast-classifier),)
|
||||
$(INSTALL_DIR) $(1)/usr/include
|
||||
$(CP) $(PKG_BUILD_DIR)/fast-classifier.h $(1)/usr/include/
|
||||
endif
|
||||
endef
|
||||
endif
|
||||
|
||||
define Package/fast-classifier-example/install
|
||||
$(INSTALL_DIR) $(1)/sbin
|
||||
$(CP) $(PKG_BUILD_DIR)/userspace_fast_classifier $(1)/sbin/
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,shortcut-fe))
|
||||
$(eval $(call KernelPackage,shortcut-fe-cm))
|
||||
$(eval $(call KernelPackage,fast-classifier))
|
||||
#$(eval $(call BuildPackage,fast-classifier-example))
|
||||
|
||||
|
||||
48
package/lean/shortcut-fe/files/etc/init.d/shortcut-fe
Executable file
48
package/lean/shortcut-fe/files/etc/init.d/shortcut-fe
Executable file
@ -0,0 +1,48 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all copies.
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
#SFE connection manager has a lower priority, it should be started after other connection manager
|
||||
#to detect the existence of connection manager with higher priority
|
||||
START=72
|
||||
|
||||
have_cm() {
|
||||
[ -d "/sys/kernel/debug/ecm" ] && echo 1 && return
|
||||
|
||||
echo 0
|
||||
}
|
||||
|
||||
#load shortcut-fe connection manager
|
||||
load_sfe_cm() {
|
||||
local kernel_version=$(uname -r)
|
||||
|
||||
#shortcut-fe-drv.ko is not needed because other connection manager is not enabled
|
||||
[ -d "/sys/module/shortcut_fe_drv" ] && rmmod shortcut_fe_drv
|
||||
|
||||
[ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && {
|
||||
[ -d /sys/module/shortcut_fe_cm ] || insmod /lib/modules/$kernel_version/shortcut-fe-cm.ko
|
||||
}
|
||||
[ -e "/lib/modules/$kernel_version/fast-classifier.ko" ] && {
|
||||
[ -d /sys/module/fast_classifier ] || insmod /lib/modules/$kernel_version/fast-classifier.ko
|
||||
}
|
||||
}
|
||||
|
||||
start() {
|
||||
[ "$(have_cm)" = "1" ] || load_sfe_cm
|
||||
}
|
||||
|
||||
stop() {
|
||||
[ -d /sys/module/shortcut_fe_cm ] && rmmod shortcut_fe_cm
|
||||
[ -d /sys/module/fast_classifier ] && rmmod fast_classifier
|
||||
}
|
||||
35
package/lean/shortcut-fe/files/usr/bin/sfe_dump
Normal file
35
package/lean/shortcut-fe/files/usr/bin/sfe_dump
Normal file
@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2015 The Linux Foundation. All rights reserved.
|
||||
# Permission to use, copy, modify, and/or distribute this software for
|
||||
# any purpose with or without fee is hereby granted, provided that the
|
||||
# above copyright notice and this permission notice appear in all copies.
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
||||
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
#@sfe_dump
|
||||
#@example : sfe_dump (ipv4|ipv6)
|
||||
sfe_dump(){
|
||||
[ -e "/dev/sfe_ipv4" ] || {
|
||||
dev_num=$(cat /sys/sfe_ipv4/debug_dev)
|
||||
mknod /dev/sfe_ipv4 c $dev_num 0
|
||||
}
|
||||
[ -e "/dev/sfe_ipv6" ] || {
|
||||
dev_num=$(cat /sys/sfe_ipv6/debug_dev)
|
||||
mknod /dev/sfe_ipv6 c $dev_num 0
|
||||
}
|
||||
cat /dev/sfe_$1
|
||||
}
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
sfe_dump ipv4
|
||||
sfe_dump ipv6
|
||||
else
|
||||
sfe_dump $1
|
||||
fi
|
||||
@ -2,13 +2,22 @@
|
||||
# Makefile for Shortcut FE.
|
||||
#
|
||||
|
||||
obj-m += shortcut-fe.o shortcut-fe-ipv6.o shortcut-fe-cm.o fast-classifier.o
|
||||
obj-m += shortcut-fe.o
|
||||
|
||||
ifdef SFE_SUPPORT_IPV6
|
||||
obj-m += shortcut-fe-ipv6.o
|
||||
endif
|
||||
|
||||
obj-m += shortcut-fe-cm.o
|
||||
|
||||
shortcut-fe-objs := \
|
||||
sfe_ipv4.o
|
||||
|
||||
ifdef SFE_SUPPORT_IPV6
|
||||
shortcut-fe-ipv6-objs := \
|
||||
sfe_ipv6.o
|
||||
endif
|
||||
|
||||
shortcut-fe-cm-objs := \
|
||||
sfe_cm.o
|
||||
|
||||
|
||||
@ -1,122 +0,0 @@
|
||||
Shortcut Forwarding Engine
|
||||
--------------------------
|
||||
|
||||
Welcome to "Shortcut" :-)
|
||||
|
||||
Here's a quick FAQ:
|
||||
|
||||
|
||||
Q) What is Shortcut?
|
||||
|
||||
A) Shortcut is an in-Linux-kernel IP packet forwarding engine. It's designed
|
||||
to offer very high speed IP packet forwarding based on IP connection tracking.
|
||||
It's dramatically faster than the standard netfilter-based NAT forwarding path
|
||||
but is designed to synchronise state back to netfilter/conntrack so that it
|
||||
doesn't need to deal with all of the complexities of special cases.
|
||||
|
||||
|
||||
Q) What versions of IP does it support?
|
||||
|
||||
A) The current version only supports IPv4 but will be extended to support IPv6 in
|
||||
the future.
|
||||
|
||||
|
||||
Q) What transport protocols does it support?
|
||||
|
||||
A) TCP and UDP. It also knows enough about ICMP to spot ICMP error messages
|
||||
related to TCP and UDP and handle things accordingly.
|
||||
|
||||
|
||||
Q) Is there a design spec for this software?
|
||||
|
||||
A) Not at the moment. I'll write one when I get more time. The code is
|
||||
intended to be a good tutorial though - it's very heavily commented. If you
|
||||
find yourself reading something and not understanding it then I take that to
|
||||
mean I've probably not done a sufficently good job of explaining what it's
|
||||
doing in the comments. Let me know - I will try to fix it :-)
|
||||
|
||||
|
||||
Q) Why was it written?
|
||||
|
||||
A) It was written as a demonstration of what can be done to provide high
|
||||
performance forwarding inside the kernel. There were two initial motivations:
|
||||
|
||||
1) To provide a platform to enable research into how QoS analysis systems can
|
||||
offload work and avoid huge Linux overheads.
|
||||
|
||||
2) To provide a tool to investigate the behaviour of various processors, SoCs
|
||||
and software sets so that we can characterize and design new network processor
|
||||
SoCs.
|
||||
|
||||
|
||||
Q) How much faster is it than the Linux kernel forwarding path?
|
||||
|
||||
A) At the time of pushing this to github it's been tested on a QCA AP135.
|
||||
This has a Scorpion (QCA Scopion, not the QMC one :-)) SoC, QCA9550. The
|
||||
SoC's processor is a MIPS74K running at 720 MHz and with a DDR2 memory
|
||||
subsystem that offers a peak of 600 MT/s (16-bit transfers).
|
||||
|
||||
Running IPv4 NAT forwarding of UDP between the board's 2 GMAC ports and
|
||||
using a SmartBits 200 as a traffic generator Linux is able to forward 70k PPS.
|
||||
Once the SFE code is invoked this will increase to 350k PPS!
|
||||
|
||||
There's also a slightly hacky mode which causes SFE to bypass the Linux
|
||||
bridge layer, but this isn't really ready for use because it doesn't have
|
||||
sufficient MAC address checks or integration of statistics back to the
|
||||
Ethernet bridge, but that runs at 436k PPS.
|
||||
|
||||
|
||||
Q) Are there any diagnostics?
|
||||
|
||||
A) Yes, this is a research tool after all! There's a complex way to do this
|
||||
that's more general purpose and a simple one - here's the simple one:
|
||||
|
||||
mknod /dev/sfe c 253 0
|
||||
|
||||
The file /dev/sfe is an XML-ish output and provides details of all the
|
||||
network connections currently being offloaded. It also reports the numbers
|
||||
of packets that took various "exception" paths within the code. In addition
|
||||
it provides a summary of the number of connections, attempts to accelerate
|
||||
connections, cancel accelerations, etc. It also reports the numbers of
|
||||
packets that were forwarded and not forwarded by the engine and has some
|
||||
stats on the effectiveness of the hashing algorithm it uses.
|
||||
|
||||
|
||||
Q) How does the code interact with Linux?
|
||||
|
||||
A) There are four minor patches required to make this software run with
|
||||
Linux. These are currently against a 3.3.8 or 3.4.0 kernel:
|
||||
|
||||
* (net/core/dev.c) adds a hook to allow packets to be extracted out.
|
||||
|
||||
* (net/netfilter/nf_conntrack_proto_tcp.c) exposes a state variable inside
|
||||
netfilter that's necessary to enable TCP sequence and ACK checking within
|
||||
the offload path. Note that this specific patch is against the QCA QSDK
|
||||
patched version of 3.3.8 - there's a slightly braindead "performance"
|
||||
patch in that kernel, courtesy of the OpenWrt community that makes the
|
||||
Linux forwarding path slightly faster at the expense of losing
|
||||
functionality :-(
|
||||
|
||||
* (net/Kconfig) adds the shortcut-fe option.
|
||||
|
||||
* (net/Makefile) adds the shortcut-fe build support.
|
||||
|
||||
Once these are applied and the module is loaded then everything else
|
||||
is automatic :-) The patches are in this git repo.
|
||||
|
||||
|
||||
Q) Are any of the pieces reused from other projects?
|
||||
|
||||
A) Yes! Some of the forwarding concepts are reused from the Ubicom Network
|
||||
Accelerator that morphed into part of the Akronite NSS. This code has all
|
||||
been substantially changed though to accomodate Linux's needs.
|
||||
|
||||
There are also some pieces that I borrowed from the QCA "FastNAT" software
|
||||
written by Xiaoping Fan <xfan@qca.qualcomm.com>. Xiaoping's code was the
|
||||
first actual demonstration within QCA that this in-kernel concept could yield
|
||||
signficant performance gains.
|
||||
|
||||
|
||||
Enjoy!
|
||||
Dave Hudson <dhudson@qti.qualcomm.com>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* sfe.h
|
||||
* Shortcut forwarding engine.
|
||||
*
|
||||
* Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all copies.
|
||||
@ -15,47 +15,100 @@
|
||||
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Debug output verbosity level.
|
||||
* The following are debug macros used throughout the SFE.
|
||||
*
|
||||
* The DEBUG_LEVEL enables the followings based on its value,
|
||||
* when dynamic debug option is disabled.
|
||||
*
|
||||
* 0 = OFF
|
||||
* 1 = ASSERTS / ERRORS
|
||||
* 2 = 1 + WARN
|
||||
* 3 = 2 + INFO
|
||||
* 4 = 3 + TRACE
|
||||
*/
|
||||
#define DEBUG_LEVEL 0
|
||||
#define DEBUG_LEVEL 2
|
||||
|
||||
#if (DEBUG_LEVEL < 1)
|
||||
#define DEBUG_ASSERT(s, ...)
|
||||
#define DEBUG_ERROR(s, ...)
|
||||
#else
|
||||
#define DEBUG_ERROR(s, ...) \
|
||||
do { \
|
||||
printk("%s[%u]: ERROR:", __FILE__, __LINE__); \
|
||||
printk(s, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUG_ASSERT(c, s, ...) if (!(c)) { pr_emerg("ASSERT: %s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__); BUG(); }
|
||||
#define DEBUG_ERROR(s, ...) pr_err("%s:%d:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DYNAMIC_DEBUG)
|
||||
/*
|
||||
* Compile messages for dynamic enable/disable
|
||||
*/
|
||||
#define DEBUG_WARN(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define DEBUG_INFO(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#define DEBUG_TRACE(s, ...) pr_debug("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
|
||||
/*
|
||||
* Statically compile messages at different levels
|
||||
*/
|
||||
#if (DEBUG_LEVEL < 2)
|
||||
#define DEBUG_WARN(s, ...)
|
||||
#else
|
||||
#define DEBUG_WARN(s, ...) \
|
||||
do { \
|
||||
printk("%s[%u]: WARN:", __FILE__, __LINE__); \
|
||||
printk(s, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUG_WARN(s, ...) pr_warn("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if (DEBUG_LEVEL < 3)
|
||||
#define DEBUG_INFO(s, ...)
|
||||
#else
|
||||
#define DEBUG_INFO(s, ...) \
|
||||
do { \
|
||||
printk("%s[%u]: INFO:", __FILE__, __LINE__); \
|
||||
printk(s, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUG_INFO(s, ...) pr_notice("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if (DEBUG_LEVEL < 4)
|
||||
#define DEBUG_TRACE(s, ...)
|
||||
#else
|
||||
#define DEBUG_TRACE(s, ...) \
|
||||
do { \
|
||||
printk("%s[%u]: TRACE:", __FILE__, __LINE__); \
|
||||
printk(s, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#define DEBUG_TRACE(s, ...) pr_info("%s[%d]:" s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
typedef int (*flow_cookie_set_func_t)(u32 protocol, __be32 src_ip, __be16 src_port,
|
||||
__be32 dst_ip, __be16 dst_port, u16 flow_cookie);
|
||||
/*
|
||||
* sfe_register_flow_cookie_cb
|
||||
* register a function in SFE to let SFE use this function to configure flow cookie for a flow
|
||||
*
|
||||
* Hardware driver which support flow cookie should register a callback function in SFE. Then SFE
|
||||
* can use this function to configure flow cookie for a flow.
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb);
|
||||
|
||||
/*
|
||||
* sfe_unregister_flow_cookie_cb
|
||||
* unregister function which is used to configure flow cookie for a flow
|
||||
*
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb);
|
||||
|
||||
typedef int (*sfe_ipv6_flow_cookie_set_func_t)(u32 protocol, __be32 src_ip[4], __be16 src_port,
|
||||
__be32 dst_ip[4], __be16 dst_port, u16 flow_cookie);
|
||||
|
||||
/*
|
||||
* sfe_ipv6_register_flow_cookie_cb
|
||||
* register a function in SFE to let SFE use this function to configure flow cookie for a flow
|
||||
*
|
||||
* Hardware driver which support flow cookie should register a callback function in SFE. Then SFE
|
||||
* can use this function to configure flow cookie for a flow.
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb);
|
||||
|
||||
/*
|
||||
* sfe_ipv6_unregister_flow_cookie_cb
|
||||
* unregister function which is used to configure flow cookie for a flow
|
||||
*
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb);
|
||||
|
||||
#endif /*CONFIG_NF_FLOW_COOKIE*/
|
||||
|
||||
@ -17,6 +17,38 @@
|
||||
|
||||
#include <linux/version.h>
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
|
||||
#include <net/netfilter/nf_conntrack_timeout.h>
|
||||
#else
|
||||
enum udp_conntrack {
|
||||
UDP_CT_UNREPLIED,
|
||||
UDP_CT_REPLIED,
|
||||
UDP_CT_MAX
|
||||
};
|
||||
|
||||
static inline unsigned int *
|
||||
nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
|
||||
struct nf_conn_timeout *timeout_ext;
|
||||
unsigned int *timeouts;
|
||||
|
||||
timeout_ext = nf_ct_timeout_find(ct);
|
||||
if (timeout_ext)
|
||||
timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
|
||||
else
|
||||
timeouts = l4proto->get_timeouts(net);
|
||||
|
||||
return timeouts;
|
||||
#else
|
||||
return l4proto->get_timeouts(net);
|
||||
#endif /*CONFIG_NF_CONNTRACK_TIMEOUT*/
|
||||
}
|
||||
#endif /*KERNEL_VERSION(3, 7, 0)*/
|
||||
#endif /*KERNEL_VERSION(3, 4, 0)*/
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
|
||||
#define sfe_define_post_routing_hook(FN_NAME, HOOKNUM, OPS, SKB, UNUSED, OUT, OKFN) \
|
||||
static unsigned int FN_NAME(void *priv, \
|
||||
@ -131,8 +163,33 @@ static inline struct net_device *sfe_dev_get_master(struct net_device *dev)
|
||||
#define SFE_ACCT_COUNTER(NM) (NM)
|
||||
#endif
|
||||
|
||||
#define sfe_hash_for_each_possible(name, obj, member, key) \
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
|
||||
#define sfe_hash_for_each_possible(name, obj, node, member, key) \
|
||||
hash_for_each_possible(name, obj, member, key)
|
||||
#else
|
||||
#define sfe_hash_for_each_possible(name, obj, node, member, key) \
|
||||
hash_for_each_possible(name, obj, node, member, key)
|
||||
#endif
|
||||
|
||||
#define sfe_hash_for_each(name, bkt, obj, member) \
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
|
||||
#define sfe_hash_for_each(name, bkt, node, obj, member) \
|
||||
hash_for_each(name, bkt, obj, member)
|
||||
#else
|
||||
#define sfe_hash_for_each(name, bkt, node, obj, member) \
|
||||
hash_for_each(name, bkt, node, obj, member)
|
||||
#endif
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
|
||||
#define sfe_dst_get_neighbour(dst, daddr) dst_neigh_lookup(dst, daddr)
|
||||
#else
|
||||
static inline struct neighbour *
|
||||
sfe_dst_get_neighbour(struct dst_entry *dst, void *daddr)
|
||||
{
|
||||
struct neighbour *neigh = dst_get_neighbour_noref(dst);
|
||||
|
||||
if (neigh)
|
||||
neigh_hold(neigh);
|
||||
|
||||
return neigh;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* sfe-cm.c
|
||||
* Shortcut forwarding engine connection manager.
|
||||
*
|
||||
* Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all copies.
|
||||
@ -29,10 +29,9 @@
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_timeout.h>
|
||||
#include <linux/netfilter/xt_dscp.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "sfe.h"
|
||||
#include "sfe_cm.h"
|
||||
@ -103,7 +102,6 @@ struct sfe_cm {
|
||||
|
||||
static struct sfe_cm __sc;
|
||||
|
||||
|
||||
/*
|
||||
* sfe_cm_incr_exceptions()
|
||||
* increase an exception counter.
|
||||
@ -123,7 +121,7 @@ static inline void sfe_cm_incr_exceptions(sfe_cm_exception_t except)
|
||||
*
|
||||
* Returns 1 if the packet is forwarded or 0 if it isn't.
|
||||
*/
|
||||
static int sfe_cm_recv(struct sk_buff *skb)
|
||||
int sfe_cm_recv(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev;
|
||||
|
||||
@ -136,16 +134,6 @@ static int sfe_cm_recv(struct sk_buff *skb)
|
||||
|
||||
dev = skb->dev;
|
||||
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
/*
|
||||
* If ingress Qdisc configured, and packet not processed by ingress Qdisc yet
|
||||
* We cannot accelerate this packet.
|
||||
*/
|
||||
if (dev->ingress_queue && !(skb->tc_verd & TC_NCLS)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We're only interested in IPv4 and IPv6 packets.
|
||||
*/
|
||||
@ -232,7 +220,11 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device
|
||||
|
||||
dst = (struct dst_entry *)rt;
|
||||
} else {
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
|
||||
rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, NULL, 0);
|
||||
#else
|
||||
rt6 = rt6_lookup(&init_net, (struct in6_addr *)addr->ip6, 0, 0, 0);
|
||||
#endif /*KERNEL_VERSION(4, 17, 0)*/
|
||||
if (!rt6) {
|
||||
goto ret_fail;
|
||||
}
|
||||
@ -241,7 +233,7 @@ static bool sfe_cm_find_dev_and_mac_addr(sfe_ip_addr_t *addr, struct net_device
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
neigh = dst_neigh_lookup(dst, addr);
|
||||
neigh = sfe_dst_get_neighbour(dst, addr);
|
||||
if (unlikely(!neigh)) {
|
||||
rcu_read_unlock();
|
||||
dst_release(dst);
|
||||
@ -297,6 +289,8 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
struct net_device *dev;
|
||||
struct net_device *src_dev;
|
||||
struct net_device *dest_dev;
|
||||
struct net_device *src_dev_tmp;
|
||||
struct net_device *dest_dev_tmp;
|
||||
struct net_device *src_br_dev = NULL;
|
||||
struct net_device *dest_br_dev = NULL;
|
||||
struct nf_conntrack_tuple orig_tuple;
|
||||
@ -358,6 +352,7 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
|
||||
/*
|
||||
* Don't process untracked connections.
|
||||
*/
|
||||
@ -366,6 +361,7 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
DEBUG_TRACE("untracked connection\n");
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
#endif /*KERNEL_VERSION(4, 12, 0)*/
|
||||
|
||||
/*
|
||||
* Unconfirmed connection may be dropped by Linux at the final step,
|
||||
@ -537,7 +533,11 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
* For packets de-capsulated from xfrm, we still can accelerate it
|
||||
* on the direction we just received the packet.
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0))
|
||||
if (unlikely(skb_ext_exist(skb, SKB_EXT_SEC_PATH))) {
|
||||
#else
|
||||
if (unlikely(skb->sp)) {
|
||||
#endif
|
||||
if (sic.protocol == IPPROTO_TCP &&
|
||||
!(sic.flags & SFE_CREATE_FLAG_NO_SEQ_CHECK)) {
|
||||
return NF_ACCEPT;
|
||||
@ -564,29 +564,29 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
* Get the net device and MAC addresses that correspond to the various source and
|
||||
* destination host addresses.
|
||||
*/
|
||||
if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip, &src_dev, sic.src_mac, is_v4)) {
|
||||
if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip, &src_dev_tmp, sic.src_mac, is_v4)) {
|
||||
sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_DEV);
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
src_dev = src_dev_tmp;
|
||||
|
||||
if (!sfe_cm_find_dev_and_mac_addr(&sic.src_ip_xlate, &dev, sic.src_mac_xlate, is_v4)) {
|
||||
sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_SRC_XLATE_DEV);
|
||||
goto done1;
|
||||
}
|
||||
|
||||
dev_put(dev);
|
||||
|
||||
if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip, &dev, sic.dest_mac, is_v4)) {
|
||||
sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_DEV);
|
||||
goto done1;
|
||||
}
|
||||
|
||||
dev_put(dev);
|
||||
|
||||
if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip_xlate, &dest_dev, sic.dest_mac_xlate, is_v4)) {
|
||||
if (!sfe_cm_find_dev_and_mac_addr(&sic.dest_ip_xlate, &dest_dev_tmp, sic.dest_mac_xlate, is_v4)) {
|
||||
sfe_cm_incr_exceptions(SFE_CM_EXCEPTION_NO_DEST_XLATE_DEV);
|
||||
goto done1;
|
||||
}
|
||||
dest_dev = dest_dev_tmp;
|
||||
|
||||
/*
|
||||
* Our devices may actually be part of a bridge interface. If that's
|
||||
@ -599,7 +599,6 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
DEBUG_TRACE("no bridge found for: %s\n", src_dev->name);
|
||||
goto done2;
|
||||
}
|
||||
|
||||
src_dev = src_br_dev;
|
||||
}
|
||||
|
||||
@ -610,7 +609,6 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
DEBUG_TRACE("no bridge found for: %s\n", dest_dev->name);
|
||||
goto done3;
|
||||
}
|
||||
|
||||
dest_dev = dest_br_dev;
|
||||
}
|
||||
|
||||
@ -619,7 +617,7 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
|
||||
sic.src_mtu = src_dev->mtu;
|
||||
sic.dest_mtu = dest_dev->mtu;
|
||||
sic.mark = skb->mark;
|
||||
|
||||
if (likely(is_v4)) {
|
||||
sfe_ipv4_create_rule(&sic);
|
||||
} else {
|
||||
@ -632,17 +630,14 @@ static unsigned int sfe_cm_post_routing(struct sk_buff *skb, int is_v4)
|
||||
if (dest_br_dev) {
|
||||
dev_put(dest_br_dev);
|
||||
}
|
||||
|
||||
done3:
|
||||
if (src_br_dev) {
|
||||
dev_put(src_br_dev);
|
||||
}
|
||||
|
||||
done2:
|
||||
dev_put(dest_dev);
|
||||
|
||||
dev_put(dest_dev_tmp);
|
||||
done1:
|
||||
dev_put(src_dev);
|
||||
dev_put(src_dev_tmp);
|
||||
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
@ -692,6 +687,7 @@ static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item)
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
|
||||
/*
|
||||
* If this is an untracked connection then we can't have any state either.
|
||||
*/
|
||||
@ -699,6 +695,7 @@ static int sfe_cm_conntrack_event(unsigned int events, struct nf_ct_event *item)
|
||||
DEBUG_TRACE("ignoring untracked conn\n");
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
#endif /*KERNEL_VERSION(4, 12, 0)*/
|
||||
|
||||
/*
|
||||
* We're only interested in destroy events.
|
||||
@ -771,7 +768,9 @@ static struct nf_ct_event_notifier sfe_cm_conntrack_notifier = {
|
||||
*/
|
||||
static struct nf_hook_ops sfe_cm_ops_post_routing[] __read_mostly = {
|
||||
SFE_IPV4_NF_POST_ROUTING_HOOK(__sfe_cm_ipv4_post_routing_hook),
|
||||
#ifdef SFE_SUPPORT_IPV6
|
||||
SFE_IPV6_NF_POST_ROUTING_HOOK(__sfe_cm_ipv6_post_routing_hook),
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@ -824,18 +823,20 @@ static void sfe_cm_sync_rule(struct sfe_connection_sync *sis)
|
||||
}
|
||||
|
||||
ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 9, 0))
|
||||
NF_CT_ASSERT(ct->timeout.data == (unsigned long)ct);
|
||||
#endif /*KERNEL_VERSION(4, 9, 0)*/
|
||||
|
||||
/*
|
||||
* Only update if this is not a fixed timeout
|
||||
*/
|
||||
if (!test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
|
||||
spin_lock_bh(&ct->lock);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||
ct->timeout += sis->delta_jiffies;
|
||||
#else
|
||||
ct->timeout.expires += sis->delta_jiffies;
|
||||
#endif
|
||||
#endif /*KERNEL_VERSION(4, 9, 0)*/
|
||||
spin_unlock_bh(&ct->lock);
|
||||
}
|
||||
|
||||
@ -872,6 +873,7 @@ static void sfe_cm_sync_rule(struct sfe_connection_sync *sis)
|
||||
}
|
||||
spin_unlock_bh(&ct->lock);
|
||||
break;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
|
||||
case IPPROTO_UDP:
|
||||
/*
|
||||
* In Linux connection track, UDP flow has two timeout values:
|
||||
@ -888,25 +890,31 @@ static void sfe_cm_sync_rule(struct sfe_connection_sync *sis)
|
||||
u_int64_t reply_pkts = atomic64_read(&SFE_ACCT_COUNTER(acct)[IP_CT_DIR_REPLY].packets);
|
||||
|
||||
if (reply_pkts != 0) {
|
||||
struct nf_conntrack_l4proto *l4proto;
|
||||
unsigned int *timeouts;
|
||||
|
||||
set_bit(IPS_SEEN_REPLY_BIT, &ct->status);
|
||||
set_bit(IPS_ASSURED_BIT, &ct->status);
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
|
||||
timeouts = nf_ct_timeout_lookup(ct);
|
||||
#else
|
||||
struct nf_conntrack_l4proto *l4proto;
|
||||
|
||||
l4proto = __nf_ct_l4proto_find((sis->is_v6 ? AF_INET6 : AF_INET), IPPROTO_UDP);
|
||||
timeouts = nf_ct_timeout_lookup(&init_net, ct, l4proto);
|
||||
#endif /*KERNEL_VERSION(4, 19, 0)*/
|
||||
|
||||
spin_lock_bh(&ct->lock);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
|
||||
ct->timeout = nfct_time_stamp + timeouts[UDP_CT_REPLIED];
|
||||
ct->timeout = jiffies + timeouts[UDP_CT_REPLIED];
|
||||
#else
|
||||
ct->timeout.expires = jiffies + timeouts[UDP_CT_REPLIED];
|
||||
#endif
|
||||
#endif /*KERNEL_VERSION(4, 9, 0)*/
|
||||
spin_unlock_bh(&ct->lock);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /*KERNEL_VERSION(3, 4, 0)*/
|
||||
}
|
||||
|
||||
/*
|
||||
@ -918,7 +926,7 @@ static void sfe_cm_sync_rule(struct sfe_connection_sync *sis)
|
||||
/*
|
||||
* sfe_cm_device_event()
|
||||
*/
|
||||
static int sfe_cm_device_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
int sfe_cm_device_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = SFE_DEV_EVENT_PTR(ptr);
|
||||
|
||||
@ -980,80 +988,11 @@ static ssize_t sfe_cm_get_exceptions(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_cm_get_stop
|
||||
* dump stop
|
||||
*/
|
||||
static ssize_t sfe_cm_get_stop(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int (*fast_recv)(struct sk_buff *skb);
|
||||
rcu_read_lock();
|
||||
fast_recv = rcu_dereference(fast_nat_recv);
|
||||
rcu_read_unlock();
|
||||
return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", fast_recv ? 0 : 1);
|
||||
}
|
||||
|
||||
static ssize_t sfe_cm_set_stop(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
u32 num;
|
||||
int (*fast_recv)(struct sk_buff *skb);
|
||||
|
||||
ret = kstrtou32(buf, 0, &num);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Hook/Unhook the receive path in the network stack.
|
||||
*/
|
||||
if (num) {
|
||||
RCU_INIT_POINTER(fast_nat_recv, NULL);
|
||||
} else {
|
||||
rcu_read_lock();
|
||||
fast_recv = rcu_dereference(fast_nat_recv);
|
||||
rcu_read_unlock();
|
||||
if (!fast_recv) {
|
||||
BUG_ON(fast_nat_recv);
|
||||
RCU_INIT_POINTER(fast_nat_recv, sfe_cm_recv);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_TRACE("sfe_cm_stop = %d\n", num);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_cm_get_defunct_all
|
||||
* dump state of SFE
|
||||
*/
|
||||
static ssize_t sfe_cm_get_defunct_all(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", 0);
|
||||
}
|
||||
|
||||
static ssize_t sfe_cm_set_defunct_all(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
sfe_ipv4_destroy_all_rules_for_dev(NULL);
|
||||
sfe_ipv6_destroy_all_rules_for_dev(NULL);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs attributes.
|
||||
*/
|
||||
static const struct device_attribute sfe_attrs[] = {
|
||||
__ATTR(exceptions, S_IRUGO, sfe_cm_get_exceptions, NULL),
|
||||
__ATTR(stop, S_IWUSR | S_IRUGO, sfe_cm_get_stop, sfe_cm_set_stop),
|
||||
__ATTR(defunct_all, S_IWUSR | S_IRUGO, sfe_cm_get_defunct_all, sfe_cm_set_defunct_all),
|
||||
};
|
||||
static const struct device_attribute sfe_cm_exceptions_attr =
|
||||
__ATTR(exceptions, S_IRUGO, sfe_cm_get_exceptions, NULL);
|
||||
|
||||
/*
|
||||
* sfe_cm_init()
|
||||
@ -1062,7 +1001,6 @@ static int __init sfe_cm_init(void)
|
||||
{
|
||||
struct sfe_cm *sc = &__sc;
|
||||
int result = -1;
|
||||
size_t i, j;
|
||||
|
||||
DEBUG_INFO("SFE CM init\n");
|
||||
|
||||
@ -1075,13 +1013,13 @@ static int __init sfe_cm_init(void)
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sfe_attrs); i++) {
|
||||
result = sysfs_create_file(sc->sys_sfe_cm, &sfe_attrs[i].attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register %s : %d\n",
|
||||
sfe_attrs[i].attr.name, result);
|
||||
goto exit2;
|
||||
}
|
||||
/*
|
||||
* Create sys/sfe_cm/exceptions
|
||||
*/
|
||||
result = sysfs_create_file(sc->sys_sfe_cm, &sfe_cm_exceptions_attr.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register exceptions file: %d\n", result);
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
sc->dev_notifier.notifier_call = sfe_cm_device_event;
|
||||
@ -1098,19 +1036,18 @@ static int __init sfe_cm_init(void)
|
||||
/*
|
||||
* Register our netfilter hooks.
|
||||
*/
|
||||
result = nf_register_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
|
||||
result = nf_register_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
|
||||
if (result < 0) {
|
||||
DEBUG_ERROR("can't register nf post routing hook: %d\n", result);
|
||||
goto exit3;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
/*
|
||||
* Register a notifier hook to get fast notifications of expired connections.
|
||||
* Note: In CONFIG_NF_CONNTRACK_CHAIN_EVENTS enabled case, nf_conntrack_register_notifier()
|
||||
* function always returns 0.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
(void)nf_conntrack_register_notifier(&init_net, &sfe_cm_conntrack_notifier);
|
||||
#else
|
||||
@ -1124,6 +1061,12 @@ static int __init sfe_cm_init(void)
|
||||
|
||||
spin_lock_init(&sc->lock);
|
||||
|
||||
/*
|
||||
* Hook the receive path in the network stack.
|
||||
*/
|
||||
BUG_ON(athrs_fast_nat_recv);
|
||||
RCU_INIT_POINTER(athrs_fast_nat_recv, sfe_cm_recv);
|
||||
|
||||
/*
|
||||
* Hook the shortcut sync callback.
|
||||
*/
|
||||
@ -1134,7 +1077,7 @@ static int __init sfe_cm_init(void)
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
exit4:
|
||||
nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
|
||||
nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
|
||||
#endif
|
||||
#endif
|
||||
exit3:
|
||||
@ -1142,9 +1085,6 @@ exit3:
|
||||
unregister_inetaddr_notifier(&sc->inet_notifier);
|
||||
unregister_netdevice_notifier(&sc->dev_notifier);
|
||||
exit2:
|
||||
for (j = 0; j < i; j++) {
|
||||
sysfs_remove_file(sc->sys_sfe_cm, &sfe_attrs[j].attr);
|
||||
}
|
||||
kobject_put(sc->sys_sfe_cm);
|
||||
|
||||
exit1:
|
||||
@ -1169,7 +1109,7 @@ static void __exit sfe_cm_exit(void)
|
||||
/*
|
||||
* Unregister our receive callback.
|
||||
*/
|
||||
RCU_INIT_POINTER(fast_nat_recv, NULL);
|
||||
RCU_INIT_POINTER(athrs_fast_nat_recv, NULL);
|
||||
|
||||
/*
|
||||
* Wait for all callbacks to complete.
|
||||
@ -1186,7 +1126,7 @@ static void __exit sfe_cm_exit(void)
|
||||
nf_conntrack_unregister_notifier(&init_net, &sfe_cm_conntrack_notifier);
|
||||
|
||||
#endif
|
||||
nf_unregister_hooks(sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
|
||||
nf_unregister_net_hooks(&init_net, sfe_cm_ops_post_routing, ARRAY_SIZE(sfe_cm_ops_post_routing));
|
||||
|
||||
unregister_inet6addr_notifier(&sc->inet6_notifier);
|
||||
unregister_inetaddr_notifier(&sc->inet_notifier);
|
||||
|
||||
@ -147,7 +147,7 @@ struct sfe_connection_mark {
|
||||
/*
|
||||
* Expose the hook for the receive processing.
|
||||
*/
|
||||
extern int (*fast_nat_recv)(struct sk_buff *skb);
|
||||
extern int (*athrs_fast_nat_recv)(struct sk_buff *skb);
|
||||
|
||||
/*
|
||||
* Expose what should be a static flag in the TCP connection tracker.
|
||||
@ -175,6 +175,7 @@ void sfe_ipv4_register_sync_rule_callback(sfe_sync_rule_callback_t callback);
|
||||
void sfe_ipv4_update_rule(struct sfe_connection_create *sic);
|
||||
void sfe_ipv4_mark_rule(struct sfe_connection_mark *mark);
|
||||
|
||||
#ifdef SFE_SUPPORT_IPV6
|
||||
/*
|
||||
* IPv6 APIs used by connection manager
|
||||
*/
|
||||
@ -185,6 +186,42 @@ void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev);
|
||||
void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback);
|
||||
void sfe_ipv6_update_rule(struct sfe_connection_create *sic);
|
||||
void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark);
|
||||
#else
|
||||
static inline int sfe_ipv6_recv(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sfe_ipv6_create_rule(struct sfe_connection_create *sic)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sfe_ipv6_destroy_rule(struct sfe_connection_destroy *sid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void sfe_ipv6_destroy_all_rules_for_dev(struct net_device *dev)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void sfe_ipv6_register_sync_rule_callback(sfe_sync_rule_callback_t callback)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void sfe_ipv6_update_rule(struct sfe_connection_create *sic)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void sfe_ipv6_mark_rule(struct sfe_connection_mark *mark)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* sfe_ipv6_addr_equal()
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* sfe_ipv4.c
|
||||
* Shortcut forwarding engine - IPv4 edition.
|
||||
*
|
||||
* Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2013-2016, 2019, The Linux Foundation. All rights reserved.
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all copies.
|
||||
@ -21,7 +21,7 @@
|
||||
#include <linux/icmp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "sfe.h"
|
||||
#include "sfe_cm.h"
|
||||
@ -38,7 +38,7 @@
|
||||
*/
|
||||
#define SFE_IPV4_UNALIGNED_IP_HEADER 1
|
||||
#if SFE_IPV4_UNALIGNED_IP_HEADER
|
||||
#define SFE_IPV4_UNALIGNED_STRUCT __attribute__((aligned(4)))
|
||||
#define SFE_IPV4_UNALIGNED_STRUCT __attribute__((packed))
|
||||
#else
|
||||
#define SFE_IPV4_UNALIGNED_STRUCT
|
||||
#endif
|
||||
@ -202,6 +202,9 @@ struct sfe_ipv4_connection_match {
|
||||
* Control the operations of the match.
|
||||
*/
|
||||
u32 flags; /* Bit flags */
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
u32 flow_cookie; /* used flow cookie, for debug */
|
||||
#endif
|
||||
#ifdef CONFIG_XFRM
|
||||
u32 flow_accel; /* The flow accelerated or not */
|
||||
#endif
|
||||
@ -300,6 +303,16 @@ struct sfe_ipv4_connection {
|
||||
#define SFE_IPV4_CONNECTION_HASH_SIZE (1 << SFE_IPV4_CONNECTION_HASH_SHIFT)
|
||||
#define SFE_IPV4_CONNECTION_HASH_MASK (SFE_IPV4_CONNECTION_HASH_SIZE - 1)
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
#define SFE_FLOW_COOKIE_SIZE 2048
|
||||
#define SFE_FLOW_COOKIE_MASK 0x7ff
|
||||
|
||||
struct sfe_flow_cookie_entry {
|
||||
struct sfe_ipv4_connection_match *match;
|
||||
unsigned long last_clean_time;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum sfe_ipv4_exception_events {
|
||||
SFE_IPV4_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE,
|
||||
SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION,
|
||||
@ -337,7 +350,7 @@ enum sfe_ipv4_exception_events {
|
||||
SFE_IPV4_EXCEPTION_EVENT_DATAGRAM_INCOMPLETE,
|
||||
SFE_IPV4_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE,
|
||||
SFE_IPV4_EXCEPTION_EVENT_UNHANDLED_PROTOCOL,
|
||||
SFE_IPV4_EXCEPTION_EVENT_CSUM_ERROR,
|
||||
SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR,
|
||||
SFE_IPV4_EXCEPTION_EVENT_LAST
|
||||
};
|
||||
|
||||
@ -378,7 +391,7 @@ static char *sfe_ipv4_exception_events_string[SFE_IPV4_EXCEPTION_EVENT_LAST] = {
|
||||
"DATAGRAM_INCOMPLETE",
|
||||
"IP_OPTIONS_INCOMPLETE",
|
||||
"UNHANDLED_PROTOCOL",
|
||||
"CSUM_ERROR"
|
||||
"CLONED_SKB_UNSHARE_ERROR"
|
||||
};
|
||||
|
||||
/*
|
||||
@ -402,6 +415,14 @@ struct sfe_ipv4 {
|
||||
/* Connection hash table */
|
||||
struct sfe_ipv4_connection_match *conn_match_hash[SFE_IPV4_CONNECTION_HASH_SIZE];
|
||||
/* Connection match hash table */
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
struct sfe_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE];
|
||||
/* flow cookie table*/
|
||||
flow_cookie_set_func_t flow_cookie_set_func;
|
||||
/* function used to configure flow cookie in hardware*/
|
||||
int flow_cookie_enable;
|
||||
/* Enable/disable flow cookie at runtime */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stats recorded in a sync period. These stats will be added to
|
||||
@ -759,6 +780,36 @@ static inline void sfe_ipv4_insert_sfe_ipv4_connection_match(struct sfe_ipv4 *si
|
||||
|
||||
cm->next = prev_head;
|
||||
*hash_head = cm;
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
if (!si->flow_cookie_enable)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Configure hardware to put a flow cookie in packet of this flow,
|
||||
* then we can accelerate the lookup process when we received this packet.
|
||||
*/
|
||||
for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) {
|
||||
struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx];
|
||||
|
||||
if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) {
|
||||
flow_cookie_set_func_t func;
|
||||
|
||||
rcu_read_lock();
|
||||
func = rcu_dereference(si->flow_cookie_set_func);
|
||||
if (func) {
|
||||
if (!func(cm->match_protocol, cm->match_src_ip, cm->match_src_port,
|
||||
cm->match_dest_ip, cm->match_dest_port, conn_match_idx)) {
|
||||
entry->match = cm;
|
||||
cm->flow_cookie = conn_match_idx;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -769,6 +820,36 @@ static inline void sfe_ipv4_insert_sfe_ipv4_connection_match(struct sfe_ipv4 *si
|
||||
*/
|
||||
static inline void sfe_ipv4_remove_sfe_ipv4_connection_match(struct sfe_ipv4 *si, struct sfe_ipv4_connection_match *cm)
|
||||
{
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
if (si->flow_cookie_enable) {
|
||||
/*
|
||||
* Tell hardware that we no longer need a flow cookie in packet of this flow
|
||||
*/
|
||||
unsigned int conn_match_idx;
|
||||
|
||||
for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) {
|
||||
struct sfe_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx];
|
||||
|
||||
if (cm == entry->match) {
|
||||
flow_cookie_set_func_t func;
|
||||
|
||||
rcu_read_lock();
|
||||
func = rcu_dereference(si->flow_cookie_set_func);
|
||||
if (func) {
|
||||
func(cm->match_protocol, cm->match_src_ip, cm->match_src_port,
|
||||
cm->match_dest_ip, cm->match_dest_port, 0);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
cm->flow_cookie = 0;
|
||||
entry->match = NULL;
|
||||
entry->last_clean_time = jiffies;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unlink the connection match entry from the hash.
|
||||
*/
|
||||
@ -1142,7 +1223,14 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne
|
||||
/*
|
||||
* Look for a connection match.
|
||||
*/
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match;
|
||||
if (unlikely(!cm)) {
|
||||
cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port);
|
||||
}
|
||||
#else
|
||||
cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port);
|
||||
#endif
|
||||
if (unlikely(!cm)) {
|
||||
si->exception_events[SFE_IPV4_EXCEPTION_EVENT_UDP_NO_CONNECTION]++;
|
||||
si->packets_not_forwarded++;
|
||||
@ -1217,6 +1305,30 @@ static int sfe_ipv4_recv_udp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne
|
||||
* From this point on we're good to modify the packet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check if skb was cloned. If it was, unshare it. Because
|
||||
* the data area is going to be written in this path and we don't want to
|
||||
* change the cloned skb's data section.
|
||||
*/
|
||||
if (unlikely(skb_cloned(skb))) {
|
||||
DEBUG_TRACE("%p: skb is a cloned skb\n", skb);
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
DEBUG_WARN("Failed to unshare the cloned skb\n");
|
||||
si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++;
|
||||
si->packets_not_forwarded++;
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the iph and udph pointers with the unshared skb's data area.
|
||||
*/
|
||||
iph = (struct sfe_ipv4_ip_hdr *)skb->data;
|
||||
udph = (struct sfe_ipv4_udp_hdr *)(skb->data + ihl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update DSCP
|
||||
*/
|
||||
@ -1502,7 +1614,14 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne
|
||||
/*
|
||||
* Look for a connection match.
|
||||
*/
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match;
|
||||
if (unlikely(!cm)) {
|
||||
cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port);
|
||||
}
|
||||
#else
|
||||
cm = sfe_ipv4_find_sfe_ipv4_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port);
|
||||
#endif
|
||||
if (unlikely(!cm)) {
|
||||
/*
|
||||
* We didn't get a connection but as TCP is connection-oriented that
|
||||
@ -1766,6 +1885,30 @@ static int sfe_ipv4_recv_tcp(struct sfe_ipv4 *si, struct sk_buff *skb, struct ne
|
||||
* From this point on we're good to modify the packet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check if skb was cloned. If it was, unshare it. Because
|
||||
* the data area is going to be written in this path and we don't want to
|
||||
* change the cloned skb's data section.
|
||||
*/
|
||||
if (unlikely(skb_cloned(skb))) {
|
||||
DEBUG_TRACE("%p: skb is a cloned skb\n", skb);
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
DEBUG_WARN("Failed to unshare the cloned skb\n");
|
||||
si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++;
|
||||
si->packets_not_forwarded++;
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the iph and tcph pointers with the unshared skb's data area.
|
||||
*/
|
||||
iph = (struct sfe_ipv4_ip_hdr *)skb->data;
|
||||
tcph = (struct sfe_ipv4_tcp_hdr *)(skb->data + ihl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update DSCP
|
||||
*/
|
||||
@ -2225,16 +2368,6 @@ int sfe_ipv4_recv(struct net_device *dev, struct sk_buff *skb)
|
||||
flush_on_find = true;
|
||||
}
|
||||
|
||||
if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) {
|
||||
spin_lock_bh(&si->lock);
|
||||
si->exception_events[SFE_IPV4_EXCEPTION_EVENT_CSUM_ERROR]++;
|
||||
si->packets_not_forwarded++;
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
DEBUG_TRACE("checksum of ipv4 header is invalid\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
protocol = iph->protocol;
|
||||
if (IPPROTO_UDP == protocol) {
|
||||
return sfe_ipv4_recv_udp(si, skb, dev, len, iph, ihl, flush_on_find);
|
||||
@ -2445,6 +2578,9 @@ int sfe_ipv4_create_rule(struct sfe_connection_create *sic)
|
||||
original_cm->dscp = sic->src_dscp << SFE_IPV4_DSCP_SHIFT;
|
||||
original_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK;
|
||||
}
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
original_cm->flow_cookie = 0;
|
||||
#endif
|
||||
#ifdef CONFIG_XFRM
|
||||
original_cm->flow_accel = sic->original_accel;
|
||||
#endif
|
||||
@ -2501,6 +2637,9 @@ int sfe_ipv4_create_rule(struct sfe_connection_create *sic)
|
||||
reply_cm->dscp = sic->dest_dscp << SFE_IPV4_DSCP_SHIFT;
|
||||
reply_cm->flags |= SFE_IPV4_CONNECTION_MATCH_FLAG_DSCP_REMARK;
|
||||
}
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
reply_cm->flow_cookie = 0;
|
||||
#endif
|
||||
#ifdef CONFIG_XFRM
|
||||
reply_cm->flow_accel = sic->reply_accel;
|
||||
#endif
|
||||
@ -2719,9 +2858,17 @@ another_round:
|
||||
/*
|
||||
* sfe_ipv4_periodic_sync()
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
static void sfe_ipv4_periodic_sync(struct timer_list *arg)
|
||||
#else
|
||||
static void sfe_ipv4_periodic_sync(unsigned long arg)
|
||||
#endif /*KERNEL_VERSION(4, 15, 0)*/
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg->cust_data;
|
||||
#else
|
||||
struct sfe_ipv4 *si = (struct sfe_ipv4 *)arg;
|
||||
#endif /*KERNEL_VERSION(4, 15, 0)*/
|
||||
u64 now_jiffies;
|
||||
int quota;
|
||||
sfe_sync_rule_callback_t sync_rule_callback;
|
||||
@ -2889,6 +3036,9 @@ static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si,
|
||||
u64 dest_rx_bytes;
|
||||
u64 last_sync_jiffies;
|
||||
u32 mark, src_priority, dest_priority, src_dscp, dest_dscp;
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
int src_flow_cookie, dst_flow_cookie;
|
||||
#endif
|
||||
|
||||
spin_lock_bh(&si->lock);
|
||||
|
||||
@ -2936,7 +3086,10 @@ static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si,
|
||||
dest_rx_bytes = reply_cm->rx_byte_count64;
|
||||
last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies;
|
||||
mark = c->mark;
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
src_flow_cookie = original_cm->flow_cookie;
|
||||
dst_flow_cookie = reply_cm->flow_cookie;
|
||||
#endif
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t<connection "
|
||||
@ -2951,6 +3104,9 @@ static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si,
|
||||
"dest_port=\"%u\" dest_port_xlate=\"%u\" "
|
||||
"dest_priority=\"%u\" dest_dscp=\"%u\" "
|
||||
"dest_rx_pkts=\"%llu\" dest_rx_bytes=\"%llu\" "
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
"src_flow_cookie=\"%d\" dst_flow_cookie=\"%d\" "
|
||||
#endif
|
||||
"last_sync=\"%llu\" "
|
||||
"mark=\"%08x\" />\n",
|
||||
protocol,
|
||||
@ -2964,6 +3120,9 @@ static bool sfe_ipv4_debug_dev_read_connections_connection(struct sfe_ipv4 *si,
|
||||
ntohs(dest_port), ntohs(dest_port_xlate),
|
||||
dest_priority, dest_dscp,
|
||||
dest_rx_packets, dest_rx_bytes,
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
src_flow_cookie, dst_flow_cookie,
|
||||
#endif
|
||||
last_sync_jiffies, mark);
|
||||
|
||||
if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) {
|
||||
@ -3270,6 +3429,74 @@ static struct file_operations sfe_ipv4_debug_dev_fops = {
|
||||
.release = sfe_ipv4_debug_dev_release
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
/*
|
||||
* sfe_register_flow_cookie_cb
|
||||
* register a function in SFE to let SFE use this function to configure flow cookie for a flow
|
||||
*
|
||||
* Hardware driver which support flow cookie should register a callback function in SFE. Then SFE
|
||||
* can use this function to configure flow cookie for a flow.
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_register_flow_cookie_cb(flow_cookie_set_func_t cb)
|
||||
{
|
||||
struct sfe_ipv4 *si = &__si;
|
||||
|
||||
BUG_ON(!cb);
|
||||
|
||||
if (si->flow_cookie_set_func) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rcu_assign_pointer(si->flow_cookie_set_func, cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_unregister_flow_cookie_cb
|
||||
* unregister function which is used to configure flow cookie for a flow
|
||||
*
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_unregister_flow_cookie_cb(flow_cookie_set_func_t cb)
|
||||
{
|
||||
struct sfe_ipv4 *si = &__si;
|
||||
|
||||
RCU_INIT_POINTER(si->flow_cookie_set_func, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_ipv4_get_flow_cookie()
|
||||
*/
|
||||
static ssize_t sfe_ipv4_get_flow_cookie(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfe_ipv4 *si = &__si;
|
||||
return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable);
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_ipv4_set_flow_cookie()
|
||||
*/
|
||||
static ssize_t sfe_ipv4_set_flow_cookie(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct sfe_ipv4 *si = &__si;
|
||||
strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs attributes.
|
||||
*/
|
||||
static const struct device_attribute sfe_ipv4_flow_cookie_attr =
|
||||
__ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv4_get_flow_cookie, sfe_ipv4_set_flow_cookie);
|
||||
#endif /*CONFIG_NF_FLOW_COOKIE*/
|
||||
|
||||
/*
|
||||
* sfe_ipv4_init()
|
||||
*/
|
||||
@ -3298,13 +3525,21 @@ static int __init sfe_ipv4_init(void)
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
result = sysfs_create_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result);
|
||||
goto exit3;
|
||||
}
|
||||
#endif /* CONFIG_NF_FLOW_COOKIE */
|
||||
|
||||
/*
|
||||
* Register our debug char device.
|
||||
*/
|
||||
result = register_chrdev(0, "sfe_ipv4", &sfe_ipv4_debug_dev_fops);
|
||||
if (result < 0) {
|
||||
DEBUG_ERROR("Failed to register chrdev: %d\n", result);
|
||||
goto exit3;
|
||||
goto exit4;
|
||||
}
|
||||
|
||||
si->debug_dev = result;
|
||||
@ -3312,14 +3547,24 @@ static int __init sfe_ipv4_init(void)
|
||||
/*
|
||||
* Create a timer to handle periodic statistics.
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
timer_setup(&si->timer, sfe_ipv4_periodic_sync, 0);
|
||||
si->timer.cust_data = (unsigned long)si;
|
||||
#else
|
||||
setup_timer(&si->timer, sfe_ipv4_periodic_sync, (unsigned long)si);
|
||||
#endif /*KERNEL_VERSION(4, 15, 0)*/
|
||||
mod_timer(&si->timer, jiffies + ((HZ + 99) / 100));
|
||||
|
||||
spin_lock_init(&si->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
exit4:
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr);
|
||||
|
||||
exit3:
|
||||
#endif /* CONFIG_NF_FLOW_COOKIE */
|
||||
sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr);
|
||||
|
||||
exit2:
|
||||
@ -3347,6 +3592,9 @@ static void __exit sfe_ipv4_exit(void)
|
||||
|
||||
unregister_chrdev(si->debug_dev, "sfe_ipv4");
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_flow_cookie_attr.attr);
|
||||
#endif /* CONFIG_NF_FLOW_COOKIE */
|
||||
sysfs_remove_file(si->sys_sfe_ipv4, &sfe_ipv4_debug_dev_attr.attr);
|
||||
|
||||
kobject_put(si->sys_sfe_ipv4);
|
||||
@ -3363,6 +3611,10 @@ EXPORT_SYMBOL(sfe_ipv4_destroy_all_rules_for_dev);
|
||||
EXPORT_SYMBOL(sfe_ipv4_register_sync_rule_callback);
|
||||
EXPORT_SYMBOL(sfe_ipv4_mark_rule);
|
||||
EXPORT_SYMBOL(sfe_ipv4_update_rule);
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
EXPORT_SYMBOL(sfe_register_flow_cookie_cb);
|
||||
EXPORT_SYMBOL(sfe_unregister_flow_cookie_cb);
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv4 edition");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
* sfe_ipv6.c
|
||||
* Shortcut forwarding engine - IPv6 support.
|
||||
*
|
||||
* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2016, 2019, The Linux Foundation. All rights reserved.
|
||||
* Permission to use, copy, modify, and/or distribute this software for
|
||||
* any purpose with or without fee is hereby granted, provided that the
|
||||
* above copyright notice and this permission notice appear in all copies.
|
||||
@ -21,6 +21,7 @@
|
||||
#include <linux/icmp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include "sfe.h"
|
||||
#include "sfe_cm.h"
|
||||
@ -37,7 +38,7 @@
|
||||
*/
|
||||
#define SFE_IPV6_UNALIGNED_IP_HEADER 1
|
||||
#if SFE_IPV6_UNALIGNED_IP_HEADER
|
||||
#define SFE_IPV6_UNALIGNED_STRUCT __attribute__((aligned(4)))
|
||||
#define SFE_IPV6_UNALIGNED_STRUCT __attribute__((packed))
|
||||
#else
|
||||
#define SFE_IPV6_UNALIGNED_STRUCT
|
||||
#endif
|
||||
@ -231,6 +232,9 @@ struct sfe_ipv6_connection_match {
|
||||
* Control the operations of the match.
|
||||
*/
|
||||
u32 flags; /* Bit flags */
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
u32 flow_cookie; /* used flow cookie, for debug */
|
||||
#endif
|
||||
#ifdef CONFIG_XFRM
|
||||
u32 flow_accel; /* The flow accelerated or not */
|
||||
#endif
|
||||
@ -324,6 +328,16 @@ struct sfe_ipv6_connection {
|
||||
#define SFE_IPV6_CONNECTION_HASH_SIZE (1 << SFE_IPV6_CONNECTION_HASH_SHIFT)
|
||||
#define SFE_IPV6_CONNECTION_HASH_MASK (SFE_IPV6_CONNECTION_HASH_SIZE - 1)
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
#define SFE_FLOW_COOKIE_SIZE 2048
|
||||
#define SFE_FLOW_COOKIE_MASK 0x7ff
|
||||
|
||||
struct sfe_ipv6_flow_cookie_entry {
|
||||
struct sfe_ipv6_connection_match *match;
|
||||
unsigned long last_clean_time;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum sfe_ipv6_exception_events {
|
||||
SFE_IPV6_EXCEPTION_EVENT_UDP_HEADER_INCOMPLETE,
|
||||
SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION,
|
||||
@ -362,6 +376,7 @@ enum sfe_ipv6_exception_events {
|
||||
SFE_IPV6_EXCEPTION_EVENT_IP_OPTIONS_INCOMPLETE,
|
||||
SFE_IPV6_EXCEPTION_EVENT_UNHANDLED_PROTOCOL,
|
||||
SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL,
|
||||
SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR,
|
||||
SFE_IPV6_EXCEPTION_EVENT_LAST
|
||||
};
|
||||
|
||||
@ -402,7 +417,8 @@ static char *sfe_ipv6_exception_events_string[SFE_IPV6_EXCEPTION_EVENT_LAST] = {
|
||||
"DATAGRAM_INCOMPLETE",
|
||||
"IP_OPTIONS_INCOMPLETE",
|
||||
"UNHANDLED_PROTOCOL",
|
||||
"FLOW_COOKIE_ADD_FAIL"
|
||||
"FLOW_COOKIE_ADD_FAIL",
|
||||
"CLONED_SKB_UNSHARE_ERROR"
|
||||
};
|
||||
|
||||
/*
|
||||
@ -426,6 +442,14 @@ struct sfe_ipv6 {
|
||||
/* Connection hash table */
|
||||
struct sfe_ipv6_connection_match *conn_match_hash[SFE_IPV6_CONNECTION_HASH_SIZE];
|
||||
/* Connection match hash table */
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
struct sfe_ipv6_flow_cookie_entry sfe_flow_cookie_table[SFE_FLOW_COOKIE_SIZE];
|
||||
/* flow cookie table*/
|
||||
sfe_ipv6_flow_cookie_set_func_t flow_cookie_set_func;
|
||||
/* function used to configure flow cookie in hardware*/
|
||||
int flow_cookie_enable;
|
||||
/* Enable/disable flow cookie at runtime */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stats recorded in a sync period. These stats will be added to
|
||||
@ -809,6 +833,38 @@ static inline void sfe_ipv6_insert_connection_match(struct sfe_ipv6 *si,
|
||||
|
||||
cm->next = prev_head;
|
||||
*hash_head = cm;
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
if (!si->flow_cookie_enable || !(cm->flags & (SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_SRC | SFE_IPV6_CONNECTION_MATCH_FLAG_XLATE_DEST)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Configure hardware to put a flow cookie in packet of this flow,
|
||||
* then we can accelerate the lookup process when we received this packet.
|
||||
*/
|
||||
for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) {
|
||||
struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx];
|
||||
|
||||
if ((NULL == entry->match) && time_is_before_jiffies(entry->last_clean_time + HZ)) {
|
||||
sfe_ipv6_flow_cookie_set_func_t func;
|
||||
|
||||
rcu_read_lock();
|
||||
func = rcu_dereference(si->flow_cookie_set_func);
|
||||
if (func) {
|
||||
if (!func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port,
|
||||
cm->match_dest_ip->addr, cm->match_dest_port, conn_match_idx)) {
|
||||
entry->match = cm;
|
||||
cm->flow_cookie = conn_match_idx;
|
||||
} else {
|
||||
si->exception_events[SFE_IPV6_EXCEPTION_EVENT_FLOW_COOKIE_ADD_FAIL]++;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -819,6 +875,36 @@ static inline void sfe_ipv6_insert_connection_match(struct sfe_ipv6 *si,
|
||||
*/
|
||||
static inline void sfe_ipv6_remove_connection_match(struct sfe_ipv6 *si, struct sfe_ipv6_connection_match *cm)
|
||||
{
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
if (si->flow_cookie_enable) {
|
||||
/*
|
||||
* Tell hardware that we no longer need a flow cookie in packet of this flow
|
||||
*/
|
||||
unsigned int conn_match_idx;
|
||||
|
||||
for (conn_match_idx = 1; conn_match_idx < SFE_FLOW_COOKIE_SIZE; conn_match_idx++) {
|
||||
struct sfe_ipv6_flow_cookie_entry *entry = &si->sfe_flow_cookie_table[conn_match_idx];
|
||||
|
||||
if (cm == entry->match) {
|
||||
sfe_ipv6_flow_cookie_set_func_t func;
|
||||
|
||||
rcu_read_lock();
|
||||
func = rcu_dereference(si->flow_cookie_set_func);
|
||||
if (func) {
|
||||
func(cm->match_protocol, cm->match_src_ip->addr, cm->match_src_port,
|
||||
cm->match_dest_ip->addr, cm->match_dest_port, 0);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
cm->flow_cookie = 0;
|
||||
entry->match = NULL;
|
||||
entry->last_clean_time = jiffies;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unlink the connection match entry from the hash.
|
||||
*/
|
||||
@ -1196,7 +1282,14 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne
|
||||
/*
|
||||
* Look for a connection match.
|
||||
*/
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match;
|
||||
if (unlikely(!cm)) {
|
||||
cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port);
|
||||
}
|
||||
#else
|
||||
cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_UDP, src_ip, src_port, dest_ip, dest_port);
|
||||
#endif
|
||||
if (unlikely(!cm)) {
|
||||
si->exception_events[SFE_IPV6_EXCEPTION_EVENT_UDP_NO_CONNECTION]++;
|
||||
si->packets_not_forwarded++;
|
||||
@ -1270,6 +1363,30 @@ static int sfe_ipv6_recv_udp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne
|
||||
* From this point on we're good to modify the packet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check if skb was cloned. If it was, unshare it. Because
|
||||
* the data area is going to be written in this path and we don't want to
|
||||
* change the cloned skb's data section.
|
||||
*/
|
||||
if (unlikely(skb_cloned(skb))) {
|
||||
DEBUG_TRACE("%p: skb is a cloned skb\n", skb);
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
DEBUG_WARN("Failed to unshare the cloned skb\n");
|
||||
si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++;
|
||||
si->packets_not_forwarded++;
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the iph and udph pointers with the unshared skb's data area.
|
||||
*/
|
||||
iph = (struct sfe_ipv6_ip_hdr *)skb->data;
|
||||
udph = (struct sfe_ipv6_udp_hdr *)(skb->data + ihl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update DSCP
|
||||
*/
|
||||
@ -1535,7 +1652,14 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne
|
||||
/*
|
||||
* Look for a connection match.
|
||||
*/
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
cm = si->sfe_flow_cookie_table[skb->flow_cookie & SFE_FLOW_COOKIE_MASK].match;
|
||||
if (unlikely(!cm)) {
|
||||
cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port);
|
||||
}
|
||||
#else
|
||||
cm = sfe_ipv6_find_connection_match(si, dev, IPPROTO_TCP, src_ip, src_port, dest_ip, dest_port);
|
||||
#endif
|
||||
if (unlikely(!cm)) {
|
||||
/*
|
||||
* We didn't get a connection but as TCP is connection-oriented that
|
||||
@ -1799,6 +1923,30 @@ static int sfe_ipv6_recv_tcp(struct sfe_ipv6 *si, struct sk_buff *skb, struct ne
|
||||
* From this point on we're good to modify the packet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Check if skb was cloned. If it was, unshare it. Because
|
||||
* the data area is going to be written in this path and we don't want to
|
||||
* change the cloned skb's data section.
|
||||
*/
|
||||
if (unlikely(skb_cloned(skb))) {
|
||||
DEBUG_TRACE("%p: skb is a cloned skb\n", skb);
|
||||
skb = skb_unshare(skb, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
DEBUG_WARN("Failed to unshare the cloned skb\n");
|
||||
si->exception_events[SFE_IPV6_EXCEPTION_EVENT_CLONED_SKB_UNSHARE_ERROR]++;
|
||||
si->packets_not_forwarded++;
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the iph and tcph pointers with the unshared skb's data area.
|
||||
*/
|
||||
iph = (struct sfe_ipv6_ip_hdr *)skb->data;
|
||||
tcph = (struct sfe_ipv6_tcp_hdr *)(skb->data + ihl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update DSCP
|
||||
*/
|
||||
@ -2444,6 +2592,9 @@ int sfe_ipv6_create_rule(struct sfe_connection_create *sic)
|
||||
original_cm->dscp = sic->src_dscp << SFE_IPV6_DSCP_SHIFT;
|
||||
original_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK;
|
||||
}
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
original_cm->flow_cookie = 0;
|
||||
#endif
|
||||
#ifdef CONFIG_XFRM
|
||||
original_cm->flow_accel = sic->original_accel;
|
||||
#endif
|
||||
@ -2500,6 +2651,9 @@ int sfe_ipv6_create_rule(struct sfe_connection_create *sic)
|
||||
reply_cm->dscp = sic->dest_dscp << SFE_IPV6_DSCP_SHIFT;
|
||||
reply_cm->flags |= SFE_IPV6_CONNECTION_MATCH_FLAG_DSCP_REMARK;
|
||||
}
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
reply_cm->flow_cookie = 0;
|
||||
#endif
|
||||
#ifdef CONFIG_XFRM
|
||||
reply_cm->flow_accel = sic->reply_accel;
|
||||
#endif
|
||||
@ -2712,9 +2866,17 @@ another_round:
|
||||
/*
|
||||
* sfe_ipv6_periodic_sync()
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
static void sfe_ipv6_periodic_sync(struct timer_list *arg)
|
||||
#else
|
||||
static void sfe_ipv6_periodic_sync(unsigned long arg)
|
||||
#endif /*KERNEL_VERSION(4, 15, 0)*/
|
||||
{
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg->cust_data;
|
||||
#else
|
||||
struct sfe_ipv6 *si = (struct sfe_ipv6 *)arg;
|
||||
#endif /*KERNEL_VERSION(4, 15, 0)*/
|
||||
u64 now_jiffies;
|
||||
int quota;
|
||||
sfe_sync_rule_callback_t sync_rule_callback;
|
||||
@ -2880,6 +3042,9 @@ static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si,
|
||||
u64 dest_rx_bytes;
|
||||
u64 last_sync_jiffies;
|
||||
u32 mark, src_priority, dest_priority, src_dscp, dest_dscp;
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
int src_flow_cookie, dst_flow_cookie;
|
||||
#endif
|
||||
|
||||
spin_lock_bh(&si->lock);
|
||||
|
||||
@ -2927,7 +3092,10 @@ static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si,
|
||||
dest_rx_bytes = reply_cm->rx_byte_count64;
|
||||
last_sync_jiffies = get_jiffies_64() - c->last_sync_jiffies;
|
||||
mark = c->mark;
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
src_flow_cookie = original_cm->flow_cookie;
|
||||
dst_flow_cookie = reply_cm->flow_cookie;
|
||||
#endif
|
||||
spin_unlock_bh(&si->lock);
|
||||
|
||||
bytes_read = snprintf(msg, CHAR_DEV_MSG_SIZE, "\t\t<connection "
|
||||
@ -2942,6 +3110,9 @@ static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si,
|
||||
"dest_port=\"%u\" dest_port_xlate=\"%u\" "
|
||||
"dest_priority=\"%u\" dest_dscp=\"%u\" "
|
||||
"dest_rx_pkts=\"%llu\" dest_rx_bytes=\"%llu\" "
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
"src_flow_cookie=\"%d\" dst_flow_cookie=\"%d\" "
|
||||
#endif
|
||||
"last_sync=\"%llu\" "
|
||||
"mark=\"%08x\" />\n",
|
||||
protocol,
|
||||
@ -2955,6 +3126,9 @@ static bool sfe_ipv6_debug_dev_read_connections_connection(struct sfe_ipv6 *si,
|
||||
ntohs(dest_port), ntohs(dest_port_xlate),
|
||||
dest_priority, dest_dscp,
|
||||
dest_rx_packets, dest_rx_bytes,
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
src_flow_cookie, dst_flow_cookie,
|
||||
#endif
|
||||
last_sync_jiffies, mark);
|
||||
|
||||
if (copy_to_user(buffer + *total_read, msg, CHAR_DEV_MSG_SIZE)) {
|
||||
@ -3263,6 +3437,74 @@ static struct file_operations sfe_ipv6_debug_dev_fops = {
|
||||
.release = sfe_ipv6_debug_dev_release
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
/*
|
||||
* sfe_ipv6_register_flow_cookie_cb
|
||||
* register a function in SFE to let SFE use this function to configure flow cookie for a flow
|
||||
*
|
||||
* Hardware driver which support flow cookie should register a callback function in SFE. Then SFE
|
||||
* can use this function to configure flow cookie for a flow.
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_ipv6_register_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb)
|
||||
{
|
||||
struct sfe_ipv6 *si = &__si6;
|
||||
|
||||
BUG_ON(!cb);
|
||||
|
||||
if (si->flow_cookie_set_func) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rcu_assign_pointer(si->flow_cookie_set_func, cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_ipv6_unregister_flow_cookie_cb
|
||||
* unregister function which is used to configure flow cookie for a flow
|
||||
*
|
||||
* return: 0, success; !=0, fail
|
||||
*/
|
||||
int sfe_ipv6_unregister_flow_cookie_cb(sfe_ipv6_flow_cookie_set_func_t cb)
|
||||
{
|
||||
struct sfe_ipv6 *si = &__si6;
|
||||
|
||||
RCU_INIT_POINTER(si->flow_cookie_set_func, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_ipv6_get_flow_cookie()
|
||||
*/
|
||||
static ssize_t sfe_ipv6_get_flow_cookie(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfe_ipv6 *si = &__si6;
|
||||
return snprintf(buf, (ssize_t)PAGE_SIZE, "%d\n", si->flow_cookie_enable);
|
||||
}
|
||||
|
||||
/*
|
||||
* sfe_ipv6_set_flow_cookie()
|
||||
*/
|
||||
static ssize_t sfe_ipv6_set_flow_cookie(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct sfe_ipv6 *si = &__si6;
|
||||
strict_strtol(buf, 0, (long int *)&si->flow_cookie_enable);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysfs attributes.
|
||||
*/
|
||||
static const struct device_attribute sfe_ipv6_flow_cookie_attr =
|
||||
__ATTR(flow_cookie_enable, S_IWUSR | S_IRUGO, sfe_ipv6_get_flow_cookie, sfe_ipv6_set_flow_cookie);
|
||||
#endif /*CONFIG_NF_FLOW_COOKIE*/
|
||||
|
||||
/*
|
||||
* sfe_ipv6_init()
|
||||
*/
|
||||
@ -3291,13 +3533,21 @@ static int __init sfe_ipv6_init(void)
|
||||
goto exit2;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
result = sysfs_create_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr);
|
||||
if (result) {
|
||||
DEBUG_ERROR("failed to register flow cookie enable file: %d\n", result);
|
||||
goto exit3;
|
||||
}
|
||||
#endif /* CONFIG_NF_FLOW_COOKIE */
|
||||
|
||||
/*
|
||||
* Register our debug char device.
|
||||
*/
|
||||
result = register_chrdev(0, "sfe_ipv6", &sfe_ipv6_debug_dev_fops);
|
||||
if (result < 0) {
|
||||
DEBUG_ERROR("Failed to register chrdev: %d\n", result);
|
||||
goto exit3;
|
||||
goto exit4;
|
||||
}
|
||||
|
||||
si->debug_dev = result;
|
||||
@ -3305,14 +3555,24 @@ static int __init sfe_ipv6_init(void)
|
||||
/*
|
||||
* Create a timer to handle periodic statistics.
|
||||
*/
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
|
||||
timer_setup(&si->timer, sfe_ipv6_periodic_sync, 0);
|
||||
si->timer.cust_data = (unsigned long)si;
|
||||
#else
|
||||
setup_timer(&si->timer, sfe_ipv6_periodic_sync, (unsigned long)si);
|
||||
#endif /*KERNEL_VERSION(4, 15, 0)*/
|
||||
mod_timer(&si->timer, jiffies + ((HZ + 99) / 100));
|
||||
|
||||
spin_lock_init(&si->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
exit4:
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr);
|
||||
|
||||
exit3:
|
||||
#endif /* CONFIG_NF_FLOW_COOKIE */
|
||||
sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr);
|
||||
|
||||
exit2:
|
||||
@ -3340,6 +3600,9 @@ static void __exit sfe_ipv6_exit(void)
|
||||
|
||||
unregister_chrdev(si->debug_dev, "sfe_ipv6");
|
||||
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_flow_cookie_attr.attr);
|
||||
#endif /* CONFIG_NF_FLOW_COOKIE */
|
||||
sysfs_remove_file(si->sys_sfe_ipv6, &sfe_ipv6_debug_dev_attr.attr);
|
||||
|
||||
kobject_put(si->sys_sfe_ipv6);
|
||||
@ -3355,6 +3618,10 @@ EXPORT_SYMBOL(sfe_ipv6_destroy_all_rules_for_dev);
|
||||
EXPORT_SYMBOL(sfe_ipv6_register_sync_rule_callback);
|
||||
EXPORT_SYMBOL(sfe_ipv6_mark_rule);
|
||||
EXPORT_SYMBOL(sfe_ipv6_update_rule);
|
||||
#ifdef CONFIG_NF_FLOW_COOKIE
|
||||
EXPORT_SYMBOL(sfe_ipv6_register_flow_cookie_cb);
|
||||
EXPORT_SYMBOL(sfe_ipv6_unregister_flow_cookie_cb);
|
||||
#endif
|
||||
|
||||
MODULE_DESCRIPTION("Shortcut Forwarding Engine - IPv6 support");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
@ -3,7 +3,7 @@ menu "V2Ray Configuration"
|
||||
|
||||
config V2RAY_COMPRESS_GOPROXY
|
||||
bool "Compiling with GOPROXY proxy"
|
||||
default n
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "JSON Config Support"
|
||||
|
||||
@ -10,12 +10,12 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=redsocks2
|
||||
PKG_VERSION:=0.67
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=4
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/semigodking/redsocks.git
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_SOURCE_VERSION:=53cad23a14afdd5f61a0542615beb7f4d98be728
|
||||
PKG_SOURCE_VERSION:=d94c245ea47859cda5b4b7373308589206b97bdc
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
|
||||
|
||||
@ -37,6 +37,14 @@ The name is changed to be REDSOCKS2 since this release to distinguish with origi
|
||||
This variant is useful for anti-GFW (Great Fire Wall).
|
||||
endef
|
||||
|
||||
define Package/redsocks2/conffiles
|
||||
/etc/config/redsocks2
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(call Build/Compile/Default,DISABLE_SHADOWSOCKS=true)
|
||||
endef
|
||||
|
||||
define Package/redsocks2/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/redsocks2 $(1)/usr/sbin
|
||||
|
||||
@ -1,315 +0,0 @@
|
||||
diff --git a/encrypt.c b/encrypt.c
|
||||
index ce04c6f..dc27754 100644
|
||||
--- a/encrypt.c
|
||||
+++ b/encrypt.c
|
||||
@@ -278,7 +278,7 @@ static void enc_table_init(enc_info * info, const char *pass)
|
||||
}
|
||||
}
|
||||
|
||||
-int cipher_iv_size(const cipher_kt_t *cipher)
|
||||
+int cipher_iv_size(const cipher_t *cipher)
|
||||
{
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CIPHER_iv_length(cipher);
|
||||
@@ -290,7 +290,7 @@ int cipher_iv_size(const cipher_kt_t *cipher)
|
||||
#endif
|
||||
}
|
||||
|
||||
-int cipher_key_size(const cipher_kt_t *cipher)
|
||||
+int cipher_key_size(const cipher_t *cipher)
|
||||
{
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CIPHER_key_length(cipher);
|
||||
@@ -307,102 +307,66 @@ int cipher_key_size(const cipher_kt_t *cipher)
|
||||
#endif
|
||||
}
|
||||
|
||||
-int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md,
|
||||
- const uint8_t *pass, uint8_t *key, uint8_t *iv)
|
||||
+int bytes_to_key(const cipher_t *cipher, const digest_type_t *md,
|
||||
+ const uint8_t *pass, uint8_t *key)
|
||||
{
|
||||
size_t datal;
|
||||
datal = strlen((const char *)pass);
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
- return EVP_BytesToKey(cipher, md, NULL, pass, datal, 1, key, iv);
|
||||
+ MD5_CTX c;
|
||||
+ unsigned char md_buf[MAX_MD_SIZE];
|
||||
+ int nkey;
|
||||
+ int addmd;
|
||||
+ unsigned int i, j, mds;
|
||||
+
|
||||
+ mds = 16;
|
||||
+ if (pass == NULL) return nkey;
|
||||
+ memset(&c, 0, sizeof(MD5_CTX));
|
||||
+
|
||||
+ for (j = 0, addmd = 0; j < nkey; addmd++) {
|
||||
+ MD5_Init(&c);
|
||||
+ if (addmd) {
|
||||
+ MD5_Update(&c, md_buf, mds);
|
||||
+ }
|
||||
+ MD5_Update(&c, pass, datal);
|
||||
+ MD5_Final(md_buf, &c);
|
||||
+
|
||||
+ for (i = 0; i < mds; i++, j++) {
|
||||
+ if (j >= nkey) break;
|
||||
+ key[j] = md_buf[i];
|
||||
+ }
|
||||
+ }
|
||||
+ return nkey;
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
md_context_t c;
|
||||
unsigned char md_buf[MAX_MD_SIZE];
|
||||
- int niv;
|
||||
int nkey;
|
||||
int addmd;
|
||||
- unsigned int mds;
|
||||
- unsigned int i;
|
||||
- int rv;
|
||||
+ unsigned int i, j, mds;
|
||||
|
||||
nkey = cipher_key_size(cipher);
|
||||
- niv = cipher_iv_size(cipher);
|
||||
- rv = nkey;
|
||||
- if (pass == NULL) {
|
||||
- return nkey;
|
||||
- }
|
||||
-
|
||||
+ mds = md_get_size(md);
|
||||
memset(&c, 0, sizeof(md_context_t));
|
||||
- if (md_init_ctx(&c, md)) {
|
||||
- return 0;
|
||||
- }
|
||||
- addmd = 0;
|
||||
- mds = md_get_size(md);
|
||||
- for (;; ) {
|
||||
- int error;
|
||||
- do {
|
||||
- error = 1;
|
||||
- if (md_starts(&c)) {
|
||||
- break;
|
||||
- }
|
||||
- if (addmd) {
|
||||
- if (md_update(&c, &(md_buf[0]), mds)) {
|
||||
- break;
|
||||
- }
|
||||
- } else {
|
||||
- addmd = 1;
|
||||
- }
|
||||
- if (md_update(&c, pass, datal)) {
|
||||
- break;
|
||||
- }
|
||||
- if (md_finish(&c, &(md_buf[0]))) {
|
||||
- break;
|
||||
- }
|
||||
- error = 0;
|
||||
- } while (0);
|
||||
- if (error) {
|
||||
- md_free_ctx(&c);
|
||||
- memset(md_buf, 0, MAX_MD_SIZE);
|
||||
- return 0;
|
||||
- }
|
||||
|
||||
- i = 0;
|
||||
- if (nkey) {
|
||||
- for (;; ) {
|
||||
- if (nkey == 0) {
|
||||
- break;
|
||||
- }
|
||||
- if (i == mds) {
|
||||
- break;
|
||||
- }
|
||||
- if (key != NULL) {
|
||||
- *(key++) = md_buf[i];
|
||||
- }
|
||||
- nkey--;
|
||||
- i++;
|
||||
- }
|
||||
- }
|
||||
- if (niv && (i != mds)) {
|
||||
- for (;; ) {
|
||||
- if (niv == 0) {
|
||||
- break;
|
||||
- }
|
||||
- if (i == mds) {
|
||||
- break;
|
||||
- }
|
||||
- if (iv != NULL) {
|
||||
- *(iv++) = md_buf[i];
|
||||
- }
|
||||
- niv--;
|
||||
- i++;
|
||||
- }
|
||||
+ if (pass == NULL) return nkey;
|
||||
+ if (md_init_ctx(&c, md)) return 0;
|
||||
+
|
||||
+ for (j = 0, addmd = 0; j < nkey; addmd++) {
|
||||
+ md_starts(&c);
|
||||
+ if (addmd) {
|
||||
+ md_update(&c, md_buf, mds);
|
||||
}
|
||||
- if ((nkey == 0) && (niv == 0)) {
|
||||
- break;
|
||||
+ md_update(&c, pass, datal);
|
||||
+ md_finish(&c, md_buf);
|
||||
+
|
||||
+ for (i = 0; i < mds; i++, j++) {
|
||||
+ if (j >= nkey) break;
|
||||
+ key[j] = md_buf[i];
|
||||
}
|
||||
}
|
||||
+
|
||||
md_free_ctx(&c);
|
||||
- memset(md_buf, 0, MAX_MD_SIZE);
|
||||
- return rv;
|
||||
+ return nkey;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -472,7 +436,7 @@ int rand_bytes(uint8_t *output, int len)
|
||||
#endif
|
||||
}
|
||||
|
||||
-const cipher_kt_t *get_cipher_type(int method)
|
||||
+const cipher_t *get_cipher_type(int method)
|
||||
{
|
||||
if (method <= TABLE || method >= CIPHER_NUM) {
|
||||
//LOGE("get_cipher_type(): Illegal method");
|
||||
@@ -548,7 +512,7 @@ static int cipher_context_init(const enc_info * info, cipher_ctx_t *ctx, int enc
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
- const cipher_kt_t *cipher = get_cipher_type(method);
|
||||
+ const cipher_t *cipher = get_cipher_type(method);
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
if (cipher == NULL) {
|
||||
// Cipher is not found in OpenSSL library
|
||||
@@ -560,7 +524,7 @@ static int cipher_context_init(const enc_info * info, cipher_ctx_t *ctx, int enc
|
||||
return -1;
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_set_key_length(evp, info->key_len)) {
|
||||
- EVP_CIPHER_CTX_cleanup(evp);
|
||||
+ EVP_CIPHER_CTX_free(ctx->evp);
|
||||
// Invalid key length
|
||||
return -1;
|
||||
}
|
||||
@@ -649,7 +613,7 @@ static void cipher_context_set_iv(const enc_info * info, cipher_ctx_t *ctx, uint
|
||||
}
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
if (!EVP_CipherInit_ex(evp, NULL, NULL, true_key, iv, enc)) {
|
||||
- EVP_CIPHER_CTX_cleanup(evp);
|
||||
+ EVP_CIPHER_CTX_free(ctx->evp);
|
||||
//FATAL("Cannot set key and IV");
|
||||
}
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
@@ -698,7 +662,7 @@ static void cipher_context_release(enc_info * info, cipher_ctx_t *ctx)
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
- EVP_CIPHER_CTX_cleanup(evp);
|
||||
+ EVP_CIPHER_CTX_free(ctx->evp);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
cipher_free_ctx(evp);
|
||||
#endif
|
||||
@@ -730,7 +694,7 @@ static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, int *olen,
|
||||
size_t ss_calc_buffer_size(struct enc_ctx * ctx, size_t ilen)
|
||||
{
|
||||
int method = ctx->info->method;
|
||||
- const cipher_kt_t *cipher = get_cipher_type(method);
|
||||
+ const cipher_t *cipher = get_cipher_type(method);
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
if (ctx->init)
|
||||
return ilen + EVP_CIPHER_block_size(cipher);
|
||||
@@ -913,10 +877,7 @@ static int enc_key_init(enc_info * info, int method, const char *pass)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#endif
|
||||
|
||||
- uint8_t iv[MAX_IV_LENGTH];
|
||||
-
|
||||
- cipher_kt_t *cipher = NULL;
|
||||
- cipher_kt_t cipher_info;
|
||||
+ cipher_t *cipher;
|
||||
|
||||
|
||||
if (method == SALSA20 || method == CHACHA20) {
|
||||
@@ -924,11 +885,9 @@ static int enc_key_init(enc_info * info, int method, const char *pass)
|
||||
if (sodium_init() == -1) {
|
||||
//FATAL("Failed to initialize sodium");
|
||||
}
|
||||
- // Fake cipher
|
||||
- cipher = (cipher_kt_t *)&cipher_info;
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
- cipher->key_len = supported_ciphers_key_size[method];
|
||||
- cipher->iv_len = supported_ciphers_iv_size[method];
|
||||
+ cipher.key_len = supported_ciphers_key_size[method];
|
||||
+ cipher.iv_len = supported_ciphers_iv_size[method];
|
||||
#endif
|
||||
#if defined(USE_CRYPTO_POLARSSL)
|
||||
cipher->base = NULL;
|
||||
@@ -937,7 +896,7 @@ static int enc_key_init(enc_info * info, int method, const char *pass)
|
||||
#endif
|
||||
*/
|
||||
} else {
|
||||
- cipher = (cipher_kt_t *)get_cipher_type(method);
|
||||
+ cipher = (cipher_t *)get_cipher_type(method);
|
||||
}
|
||||
|
||||
if (cipher == NULL) {
|
||||
@@ -947,7 +906,7 @@ static int enc_key_init(enc_info * info, int method, const char *pass)
|
||||
cipher_info.base = NULL;
|
||||
cipher_info.key_length = supported_ciphers_key_size[method] * 8;
|
||||
cipher_info.iv_size = supported_ciphers_iv_size[method];
|
||||
- cipher = (cipher_kt_t *)&cipher_info;
|
||||
+ cipher = (cipher_t *)&cipher_info;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -959,7 +918,7 @@ static int enc_key_init(enc_info * info, int method, const char *pass)
|
||||
if (md == NULL)
|
||||
return -1;
|
||||
|
||||
- info->key_len = bytes_to_key(cipher, md, (const uint8_t *)pass, info->key, iv);
|
||||
+ info->key_len = bytes_to_key(&cipher, md, (const uint8_t *)pass, info->key);
|
||||
if (info->key_len == 0) {
|
||||
//FATAL("Cannot generate key and IV");
|
||||
return -1;
|
||||
@@ -967,7 +926,7 @@ static int enc_key_init(enc_info * info, int method, const char *pass)
|
||||
if (method == RC4_MD5) {
|
||||
info->iv_len = 16;
|
||||
} else {
|
||||
- info->iv_len = cipher_iv_size(cipher);
|
||||
+ info->iv_len = cipher_iv_size(&cipher);
|
||||
}
|
||||
info->method = method;
|
||||
return method;
|
||||
diff --git a/encrypt.h b/encrypt.h
|
||||
index 61b3fc7..c3359d0 100644
|
||||
--- a/encrypt.h
|
||||
+++ b/encrypt.h
|
||||
@@ -45,7 +45,7 @@
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
|
||||
#include <openssl/evp.h>
|
||||
-typedef EVP_CIPHER cipher_kt_t;
|
||||
+typedef EVP_CIPHER cipher_t;
|
||||
typedef EVP_CIPHER_CTX cipher_evp_t;
|
||||
typedef EVP_MD digest_type_t;
|
||||
#define MAX_KEY_LENGTH EVP_MAX_KEY_LENGTH
|
||||
@@ -56,7 +56,7 @@ typedef EVP_MD digest_type_t;
|
||||
|
||||
#include <polarssl/cipher.h>
|
||||
#include <polarssl/md.h>
|
||||
-typedef cipher_info_t cipher_kt_t;
|
||||
+typedef cipher_info_t cipher_t;
|
||||
typedef cipher_context_t cipher_evp_t;
|
||||
typedef md_info_t digest_type_t;
|
||||
#define MAX_KEY_LENGTH 64
|
||||
@@ -89,7 +89,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
- cipher_evp_t evp;
|
||||
+ cipher_evp_t *evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t cc;
|
||||
#endif
|
||||
@ -1,15 +0,0 @@
|
||||
diff --git a/utils.c b/utils.c
|
||||
index 9fe148e..196a04e 100644
|
||||
--- a/utils.c
|
||||
+++ b/utils.c
|
||||
@@ -62,7 +62,9 @@ int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inadd
|
||||
if (
|
||||
cmsg->cmsg_level == SOL_IP &&
|
||||
cmsg->cmsg_type == IP_ORIGDSTADDR &&
|
||||
- cmsg->cmsg_len >= CMSG_LEN(sizeof(*toaddr))
|
||||
+ (cmsg->cmsg_len == CMSG_LEN(sizeof(struct sockaddr_in))
|
||||
+ || cmsg->cmsg_len == CMSG_LEN(sizeof(struct sockaddr_in6))) &&
|
||||
+ cmsg->cmsg_len <= CMSG_LEN(sizeof(*toaddr))
|
||||
) {
|
||||
struct sockaddr_in* cmsgaddr = (struct sockaddr_in*)CMSG_DATA(cmsg);
|
||||
memcpy(toaddr, cmsgaddr, sizeof(*toaddr));
|
||||
@ -8,14 +8,14 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=dropbear
|
||||
PKG_VERSION:=2020.79
|
||||
PKG_VERSION:=2020.80
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
||||
PKG_SOURCE_URL:= \
|
||||
http://matt.ucc.asn.au/dropbear/releases/ \
|
||||
https://dropbear.nl/mirror/releases/
|
||||
PKG_HASH:=084f00546b1610a3422a0773e2c04cbe1a220d984209e033b548b49f379cc441
|
||||
PKG_HASH:=d927941b91f2da150b2033f1a88b6a47999bf0afb1493a73e9216cffdb5d7949
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=LICENSE libtomcrypt/LICENSE libtommath/LICENSE
|
||||
|
||||
@ -238,7 +238,7 @@ killclients()
|
||||
while [ "${pid}" -ne 0 ]
|
||||
do
|
||||
# get parent process id
|
||||
pid=`cut -d ' ' -f 4 "/proc/${pid}/stat"`
|
||||
pid=$(cut -d ' ' -f 4 "/proc/${pid}/stat")
|
||||
[ "${pid}" -eq 0 ] && break
|
||||
|
||||
# check if client connection
|
||||
@ -249,14 +249,14 @@ killclients()
|
||||
done
|
||||
|
||||
# get all server pids that should be ignored
|
||||
for server in `cat /var/run/${NAME}.*.pid`
|
||||
for server in $(cat /var/run/${NAME}.*.pid)
|
||||
do
|
||||
append ignore "${server}"
|
||||
done
|
||||
|
||||
# get all running pids and kill client connections
|
||||
local skip
|
||||
for pid in `pidof "${NAME}"`
|
||||
for pid in $(pidof "${NAME}")
|
||||
do
|
||||
# check if correct program, otherwise process next pid
|
||||
grep -F -q -e "${PROG}" "/proc/${pid}/cmdline" || {
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
From 3f5c106a880a02b21739f2022746e6aa7672474c Mon Sep 17 00:00:00 2001
|
||||
From: Matt Johnston <matt@ucc.asn.au>
|
||||
Date: Tue, 23 Jun 2020 21:38:46 +0800
|
||||
Subject: [PATCH] _GNU_SOURCE for random
|
||||
|
||||
---
|
||||
includes.h | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/includes.h b/includes.h
|
||||
index e8c3e18..2789f23 100644
|
||||
--- a/includes.h
|
||||
+++ b/includes.h
|
||||
@@ -125,6 +125,8 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RANDOM_H
|
||||
+/* uclibc needs _GNU_SOURCE */
|
||||
+#define _GNU_SOURCE
|
||||
#include <sys/random.h>
|
||||
#endif
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
From a7a67585cbc3fe5df85c641618b347a51a943356 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Johnston <matt@ucc.asn.au>
|
||||
Date: Tue, 23 Jun 2020 22:24:58 +0800
|
||||
Subject: [PATCH] move GNU_SOURCE earlier
|
||||
|
||||
---
|
||||
includes.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/includes.h b/includes.h
|
||||
index 2789f23..884ebf7 100644
|
||||
--- a/includes.h
|
||||
+++ b/includes.h
|
||||
@@ -25,6 +25,8 @@
|
||||
#ifndef DROPBEAR_INCLUDES_H_
|
||||
#define DROPBEAR_INCLUDES_H_
|
||||
|
||||
+/* uclibc needs _GNU_SOURCE, maybe other things? */
|
||||
+#define _GNU_SOURCE
|
||||
|
||||
#include "options.h"
|
||||
#include "debug.h"
|
||||
@@ -125,8 +127,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_RANDOM_H
|
||||
-/* uclibc needs _GNU_SOURCE */
|
||||
-#define _GNU_SOURCE
|
||||
#include <sys/random.h>
|
||||
#endif
|
||||
|
||||
--
|
||||
2.25.1
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
From: Matt Johnston <matt@ucc.asn.au>
|
||||
Date: Thu, 18 Jun 2020 19:12:07 +0800
|
||||
Subject: Disable toom and karatsuba for new libtommath
|
||||
|
||||
--- a/libtommath/tommath_class.h
|
||||
+++ b/libtommath/tommath_class.h
|
||||
@@ -1312,6 +1312,10 @@
|
||||
#undef BN_MP_KARATSUBA_SQR_C
|
||||
#undef BN_MP_TOOM_MUL_C
|
||||
#undef BN_MP_TOOM_SQR_C
|
||||
+#undef BN_S_MP_KARATSUBA_MUL_C
|
||||
+#undef BN_S_MP_KARATSUBA_SQR_C
|
||||
+#undef BN_S_MP_TOOM_MUL_C
|
||||
+#undef BN_S_MP_TOOM_SQR_C
|
||||
|
||||
#include "dbmalloc.h"
|
||||
#define MP_MALLOC m_malloc
|
||||
@ -8,7 +8,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=curl
|
||||
PKG_VERSION:=7.70.0
|
||||
PKG_VERSION:=7.71.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||
@ -16,7 +16,7 @@ PKG_SOURCE_URL:=https://dl.uxnr.de/mirror/curl/ \
|
||||
https://curl.mirror.anstey.ca/ \
|
||||
https://curl.askapache.com/download/ \
|
||||
https://curl.haxx.se/download/
|
||||
PKG_HASH:=032f43f2674008c761af19bf536374128c16241fb234699a55f9fb603fcfbae7
|
||||
PKG_HASH:=cdf18794393d8bead915312708a9e5d819c6e9919de14b20d5c8e7987abd9772
|
||||
|
||||
PKG_LICENSE:=MIT
|
||||
PKG_LICENSE_FILES:=COPYING
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -189,7 +189,7 @@ CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP)
|
||||
@@ -192,7 +192,7 @@ CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP)
|
||||
bin_SCRIPTS = curl-config
|
||||
|
||||
SUBDIRS = lib src
|
||||
@ -9,10 +9,10 @@
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libcurl.pc
|
||||
@@ -300,8 +300,8 @@ cygwinbin:
|
||||
@@ -303,8 +303,8 @@ cygwinbin:
|
||||
# We extend the standard install with a custom hook:
|
||||
install-data-hook:
|
||||
(cd include && $(MAKE) install)
|
||||
(cd include && $(MAKE) install)
|
||||
- (cd docs && $(MAKE) install)
|
||||
- (cd docs/libcurl && $(MAKE) install)
|
||||
+ #(cd docs && $(MAKE) install)
|
||||
|
||||
@ -69,7 +69,7 @@ zram_getdev()
|
||||
local zdev=$( zram_dev )
|
||||
|
||||
if [ "$(mount | grep $zdev)" ]; then
|
||||
local idx=`cat /sys/class/zram-control/hot_add`
|
||||
local idx=$(cat /sys/class/zram-control/hot_add)
|
||||
zdev="$( zram_dev $idx )"
|
||||
fi
|
||||
|
||||
@ -85,7 +85,7 @@ zram_comp_algo()
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ `grep -c "$zram_comp_algo" /sys/block/$( basename $dev )/comp_algorithm` -ne 0 ]; then
|
||||
if [ $(grep -c "$zram_comp_algo" /sys/block/$( basename $dev )/comp_algorithm) -ne 0 ]; then
|
||||
logger -s -t zram_comp_algo -p daemon.debug "Set compression algorithm '$zram_comp_algo' for zram '$dev'"
|
||||
echo $zram_comp_algo > "/sys/block/$( basename $dev )/comp_algorithm"
|
||||
else
|
||||
|
||||
@ -13,7 +13,7 @@ FEATURES:=usbgadget
|
||||
CPU_TYPE:=24kc
|
||||
SUBTARGETS:=generic tiny nand mikrotik
|
||||
|
||||
KERNEL_PATCHVER:=4.9
|
||||
KERNEL_PATCHVER:=4.14
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
|
||||
@ -276,7 +276,7 @@
|
||||
case IPV6_2292HOPOPTS:
|
||||
--- a/net/ipv6/ip6_gre.c
|
||||
+++ b/net/ipv6/ip6_gre.c
|
||||
@@ -397,7 +397,7 @@ static void ip6gre_err(struct sk_buff *s
|
||||
@@ -400,7 +400,7 @@ static void ip6gre_err(struct sk_buff *s
|
||||
return;
|
||||
ipv6h = (const struct ipv6hdr *)skb->data;
|
||||
greh = (const struct gre_base_hdr *)(skb->data + offset);
|
||||
|
||||
@ -267,7 +267,7 @@
|
||||
case IPV6_2292HOPOPTS:
|
||||
--- a/net/ipv6/ip6_gre.c
|
||||
+++ b/net/ipv6/ip6_gre.c
|
||||
@@ -397,7 +397,7 @@ static void ip6gre_err(struct sk_buff *s
|
||||
@@ -400,7 +400,7 @@ static void ip6gre_err(struct sk_buff *s
|
||||
return;
|
||||
ipv6h = (const struct ipv6hdr *)skb->data;
|
||||
greh = (const struct gre_base_hdr *)(skb->data + offset);
|
||||
|
||||
@ -55,7 +55,7 @@ Cc: Kir Kolyshkin <kir@openvz.org>
|
||||
rwlock_t sk_callback_lock;
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -2748,6 +2748,7 @@ void sock_init_data(struct socket *sock,
|
||||
@@ -2750,6 +2750,7 @@ void sock_init_data(struct socket *sock,
|
||||
|
||||
sk->sk_max_pacing_rate = ~0U;
|
||||
sk->sk_pacing_rate = ~0U;
|
||||
|
||||
@ -0,0 +1,170 @@
|
||||
From b0c19ed6088ab41dd2a727b60594b7297c15d6ce Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
|
||||
Date: Fri, 29 May 2020 14:43:44 +0200
|
||||
Subject: [PATCH] sch_cake: Take advantage of skb->hash where appropriate
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
While the other fq-based qdiscs take advantage of skb->hash and doesn't
|
||||
recompute it if it is already set, sch_cake does not.
|
||||
|
||||
This was a deliberate choice because sch_cake hashes various parts of the
|
||||
packet header to support its advanced flow isolation modes. However,
|
||||
foregoing the use of skb->hash entirely loses a few important benefits:
|
||||
|
||||
- When skb->hash is set by hardware, a few CPU cycles can be saved by not
|
||||
hashing again in software.
|
||||
|
||||
- Tunnel encapsulations will generally preserve the value of skb->hash from
|
||||
before the encapsulation, which allows flow-based qdiscs to distinguish
|
||||
between flows even though the outer packet header no longer has flow
|
||||
information.
|
||||
|
||||
It turns out that we can preserve these desirable properties in many cases,
|
||||
while still supporting the advanced flow isolation properties of sch_cake.
|
||||
This patch does so by reusing the skb->hash value as the flow_hash part of
|
||||
the hashing procedure in cake_hash() only in the following conditions:
|
||||
|
||||
- If the skb->hash is marked as covering the flow headers (skb->l4_hash is
|
||||
set)
|
||||
|
||||
AND
|
||||
|
||||
- NAT header rewriting is either disabled, or did not change any values
|
||||
used for hashing. The latter is important to match local-origin packets
|
||||
such as those of a tunnel endpoint.
|
||||
|
||||
The immediate motivation for fixing this was the recent patch to WireGuard
|
||||
to preserve the skb->hash on encapsulation. As such, this is also what I
|
||||
tested against; with this patch, added latency under load for competing
|
||||
flows drops from ~8 ms to sub-1ms on an RRUL test over a WireGuard tunnel
|
||||
going through a virtual link shaped to 1Gbps using sch_cake. This matches
|
||||
the results we saw with a similar setup using sch_fq_codel when testing the
|
||||
WireGuard patch.
|
||||
|
||||
Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
---
|
||||
net/sched/sch_cake.c | 65 ++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 51 insertions(+), 14 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -584,26 +584,48 @@ static bool cobalt_should_drop(struct co
|
||||
return drop;
|
||||
}
|
||||
|
||||
-static void cake_update_flowkeys(struct flow_keys *keys,
|
||||
+static bool cake_update_flowkeys(struct flow_keys *keys,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
|
||||
struct nf_conntrack_tuple tuple = {};
|
||||
- bool rev = !skb->_nfct;
|
||||
+ bool rev = !skb->_nfct, upd = false;
|
||||
+ __be32 ip;
|
||||
|
||||
if (tc_skb_protocol(skb) != htons(ETH_P_IP))
|
||||
- return;
|
||||
+ return false;
|
||||
|
||||
if (!nf_ct_get_tuple_skb(&tuple, skb))
|
||||
- return;
|
||||
+ return false;
|
||||
|
||||
- keys->addrs.v4addrs.src = rev ? tuple.dst.u3.ip : tuple.src.u3.ip;
|
||||
- keys->addrs.v4addrs.dst = rev ? tuple.src.u3.ip : tuple.dst.u3.ip;
|
||||
+ ip = rev ? tuple.dst.u3.ip : tuple.src.u3.ip;
|
||||
+ if (ip != keys->addrs.v4addrs.src) {
|
||||
+ keys->addrs.v4addrs.src = ip;
|
||||
+ upd = true;
|
||||
+ }
|
||||
+ ip = rev ? tuple.src.u3.ip : tuple.dst.u3.ip;
|
||||
+ if (ip != keys->addrs.v4addrs.dst) {
|
||||
+ keys->addrs.v4addrs.dst = ip;
|
||||
+ upd = true;
|
||||
+ }
|
||||
|
||||
if (keys->ports.ports) {
|
||||
- keys->ports.src = rev ? tuple.dst.u.all : tuple.src.u.all;
|
||||
- keys->ports.dst = rev ? tuple.src.u.all : tuple.dst.u.all;
|
||||
+ __be16 port;
|
||||
+
|
||||
+ port = rev ? tuple.dst.u.all : tuple.src.u.all;
|
||||
+ if (port != keys->ports.src) {
|
||||
+ keys->ports.src = port;
|
||||
+ upd = true;
|
||||
+ }
|
||||
+ port = rev ? tuple.src.u.all : tuple.dst.u.all;
|
||||
+ if (port != keys->ports.dst) {
|
||||
+ port = keys->ports.dst;
|
||||
+ upd = true;
|
||||
+ }
|
||||
}
|
||||
+ return upd;
|
||||
+#else
|
||||
+ return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -624,23 +646,36 @@ static bool cake_ddst(int flow_mode)
|
||||
static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
|
||||
int flow_mode, u16 flow_override, u16 host_override)
|
||||
{
|
||||
+ bool hash_flows = (!flow_override && !!(flow_mode & CAKE_FLOW_FLOWS));
|
||||
+ bool hash_hosts = (!host_override && !!(flow_mode & CAKE_FLOW_HOSTS));
|
||||
+ bool nat_enabled = !!(flow_mode & CAKE_FLOW_NAT_FLAG);
|
||||
u32 flow_hash = 0, srchost_hash = 0, dsthost_hash = 0;
|
||||
u16 reduced_hash, srchost_idx, dsthost_idx;
|
||||
struct flow_keys keys, host_keys;
|
||||
+ bool use_skbhash = skb->l4_hash;
|
||||
|
||||
if (unlikely(flow_mode == CAKE_FLOW_NONE))
|
||||
return 0;
|
||||
|
||||
- /* If both overrides are set we can skip packet dissection entirely */
|
||||
- if ((flow_override || !(flow_mode & CAKE_FLOW_FLOWS)) &&
|
||||
- (host_override || !(flow_mode & CAKE_FLOW_HOSTS)))
|
||||
+ /* If both overrides are set, or we can use the SKB hash and nat mode is
|
||||
+ * disabled, we can skip packet dissection entirely. If nat mode is
|
||||
+ * enabled there's another check below after doing the conntrack lookup.
|
||||
+ */
|
||||
+ if ((!hash_flows || (use_skbhash && !nat_enabled)) && !hash_hosts)
|
||||
goto skip_hash;
|
||||
|
||||
skb_flow_dissect_flow_keys(skb, &keys,
|
||||
FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
|
||||
|
||||
- if (flow_mode & CAKE_FLOW_NAT_FLAG)
|
||||
- cake_update_flowkeys(&keys, skb);
|
||||
+ /* Don't use the SKB hash if we change the lookup keys from conntrack */
|
||||
+ if (nat_enabled && cake_update_flowkeys(&keys, skb))
|
||||
+ use_skbhash = false;
|
||||
+
|
||||
+ /* If we can still use the SKB hash and don't need the host hash, we can
|
||||
+ * skip the rest of the hashing procedure
|
||||
+ */
|
||||
+ if (use_skbhash && !hash_hosts)
|
||||
+ goto skip_hash;
|
||||
|
||||
/* flow_hash_from_keys() sorts the addresses by value, so we have
|
||||
* to preserve their order in a separate data structure to treat
|
||||
@@ -679,12 +714,14 @@ static u32 cake_hash(struct cake_tin_dat
|
||||
/* This *must* be after the above switch, since as a
|
||||
* side-effect it sorts the src and dst addresses.
|
||||
*/
|
||||
- if (flow_mode & CAKE_FLOW_FLOWS)
|
||||
+ if (hash_flows && !use_skbhash)
|
||||
flow_hash = flow_hash_from_keys(&keys);
|
||||
|
||||
skip_hash:
|
||||
if (flow_override)
|
||||
flow_hash = flow_override - 1;
|
||||
+ else if (use_skbhash)
|
||||
+ flow_hash = skb->hash;
|
||||
if (host_override) {
|
||||
dsthost_hash = host_override - 1;
|
||||
srchost_hash = host_override - 1;
|
||||
@ -0,0 +1,96 @@
|
||||
From 9208d2863ac689a563b92f2161d8d1e7127d0add Mon Sep 17 00:00:00 2001
|
||||
From: Ilya Ponetayev <i.ponetaev@ndmsystems.com>
|
||||
Date: Thu, 25 Jun 2020 22:12:07 +0200
|
||||
Subject: [PATCH] sch_cake: don't try to reallocate or unshare skb
|
||||
unconditionally
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cake_handle_diffserv() tries to linearize mac and network header parts of
|
||||
skb and to make it writable unconditionally. In some cases it leads to full
|
||||
skb reallocation, which reduces throughput and increases CPU load. Some
|
||||
measurements of IPv4 forward + NAPT on MIPS router with 580 MHz single-core
|
||||
CPU was conducted. It appears that on kernel 4.9 skb_try_make_writable()
|
||||
reallocates skb, if skb was allocated in ethernet driver via so-called
|
||||
'build skb' method from page cache (it was discovered by strange increase
|
||||
of kmalloc-2048 slab at first).
|
||||
|
||||
Obtain DSCP value via read-only skb_header_pointer() call, and leave
|
||||
linearization only for DSCP bleaching or ECN CE setting. And, as an
|
||||
additional optimisation, skip diffserv parsing entirely if it is not needed
|
||||
by the current configuration.
|
||||
|
||||
Fixes: c87b4ecdbe8d ("sch_cake: Make sure we can write the IP header before changing DSCP bits")
|
||||
Signed-off-by: Ilya Ponetayev <i.ponetaev@ndmsystems.com>
|
||||
[ fix a few style issues, reflow commit message ]
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
---
|
||||
net/sched/sch_cake.c | 41 ++++++++++++++++++++++++++++++-----------
|
||||
1 file changed, 30 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -1553,30 +1553,49 @@ static unsigned int cake_drop(struct Qdi
|
||||
|
||||
static u8 cake_handle_diffserv(struct sk_buff *skb, u16 wash)
|
||||
{
|
||||
- int wlen = skb_network_offset(skb);
|
||||
+ const int offset = skb_network_offset(skb);
|
||||
+ u16 *buf, buf_;
|
||||
u8 dscp;
|
||||
|
||||
switch (tc_skb_protocol(skb)) {
|
||||
case htons(ETH_P_IP):
|
||||
- wlen += sizeof(struct iphdr);
|
||||
- if (!pskb_may_pull(skb, wlen) ||
|
||||
- skb_try_make_writable(skb, wlen))
|
||||
+ buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
|
||||
+ if (unlikely(!buf))
|
||||
return 0;
|
||||
|
||||
- dscp = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
|
||||
- if (wash && dscp)
|
||||
+ /* ToS is in the second byte of iphdr */
|
||||
+ dscp = ipv4_get_dsfield((struct iphdr *)buf) >> 2;
|
||||
+
|
||||
+ if (wash && dscp) {
|
||||
+ const int wlen = offset + sizeof(struct iphdr);
|
||||
+
|
||||
+ if (!pskb_may_pull(skb, wlen) ||
|
||||
+ skb_try_make_writable(skb, wlen))
|
||||
+ return 0;
|
||||
+
|
||||
ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, 0);
|
||||
+ }
|
||||
+
|
||||
return dscp;
|
||||
|
||||
case htons(ETH_P_IPV6):
|
||||
- wlen += sizeof(struct ipv6hdr);
|
||||
- if (!pskb_may_pull(skb, wlen) ||
|
||||
- skb_try_make_writable(skb, wlen))
|
||||
+ buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
|
||||
+ if (unlikely(!buf))
|
||||
return 0;
|
||||
|
||||
- dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
|
||||
- if (wash && dscp)
|
||||
+ /* Traffic class is in the first and second bytes of ipv6hdr */
|
||||
+ dscp = ipv6_get_dsfield((struct ipv6hdr *)buf) >> 2;
|
||||
+
|
||||
+ if (wash && dscp) {
|
||||
+ const int wlen = offset + sizeof(struct ipv6hdr);
|
||||
+
|
||||
+ if (!pskb_may_pull(skb, wlen) ||
|
||||
+ skb_try_make_writable(skb, wlen))
|
||||
+ return 0;
|
||||
+
|
||||
ipv6_change_dsfield(ipv6_hdr(skb), INET_ECN_MASK, 0);
|
||||
+ }
|
||||
+
|
||||
return dscp;
|
||||
|
||||
case htons(ETH_P_ARP):
|
||||
@ -0,0 +1,62 @@
|
||||
From 8c95eca0bb8c4bd2231a0d581f1ad0d50c90488c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
|
||||
Date: Thu, 25 Jun 2020 22:12:08 +0200
|
||||
Subject: [PATCH] sch_cake: don't call diffserv parsing code when it is not
|
||||
needed
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
As a further optimisation of the diffserv parsing codepath, we can skip it
|
||||
entirely if CAKE is configured to neither use diffserv-based
|
||||
classification, nor to zero out the diffserv bits.
|
||||
|
||||
Fixes: c87b4ecdbe8d ("sch_cake: Make sure we can write the IP header before changing DSCP bits")
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
---
|
||||
net/sched/sch_cake.c | 13 +++++++++----
|
||||
1 file changed, 9 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -1551,7 +1551,7 @@ static unsigned int cake_drop(struct Qdi
|
||||
return idx + (tin << 16);
|
||||
}
|
||||
|
||||
-static u8 cake_handle_diffserv(struct sk_buff *skb, u16 wash)
|
||||
+static u8 cake_handle_diffserv(struct sk_buff *skb, bool wash)
|
||||
{
|
||||
const int offset = skb_network_offset(skb);
|
||||
u16 *buf, buf_;
|
||||
@@ -1612,14 +1612,17 @@ static struct cake_tin_data *cake_select
|
||||
{
|
||||
struct cake_sched_data *q = qdisc_priv(sch);
|
||||
u32 tin, mark;
|
||||
+ bool wash;
|
||||
u8 dscp;
|
||||
|
||||
/* Tin selection: Default to diffserv-based selection, allow overriding
|
||||
- * using firewall marks or skb->priority.
|
||||
+ * using firewall marks or skb->priority. Call DSCP parsing early if
|
||||
+ * wash is enabled, otherwise defer to below to skip unneeded parsing.
|
||||
*/
|
||||
- dscp = cake_handle_diffserv(skb,
|
||||
- q->rate_flags & CAKE_FLAG_WASH);
|
||||
mark = (skb->mark & q->fwmark_mask) >> q->fwmark_shft;
|
||||
+ wash = !!(q->rate_flags & CAKE_FLAG_WASH);
|
||||
+ if (wash)
|
||||
+ dscp = cake_handle_diffserv(skb, wash);
|
||||
|
||||
if (q->tin_mode == CAKE_DIFFSERV_BESTEFFORT)
|
||||
tin = 0;
|
||||
@@ -1630,6 +1633,8 @@ static struct cake_tin_data *cake_select
|
||||
tin = q->tin_order[TC_H_MIN(skb->priority) - 1];
|
||||
|
||||
else {
|
||||
+ if (!wash)
|
||||
+ dscp = cake_handle_diffserv(skb, wash);
|
||||
tin = q->tin_index[dscp];
|
||||
|
||||
if (unlikely(tin >= q->tin_cnt))
|
||||
@ -0,0 +1,40 @@
|
||||
From 3f608f0c41360b11b04c763f348b712f651c8bac Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@redhat.com>
|
||||
Date: Thu, 25 Jun 2020 22:12:09 +0200
|
||||
Subject: [PATCH] sch_cake: fix a few style nits
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
I spotted a few nits when comparing the in-tree version of sch_cake with
|
||||
the out-of-tree one: A redundant error variable declaration shadowing an
|
||||
outer declaration, and an indentation alignment issue. Fix both of these.
|
||||
|
||||
Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
---
|
||||
net/sched/sch_cake.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -2713,7 +2713,7 @@ static int cake_init(struct Qdisc *sch,
|
||||
qdisc_watchdog_init(&q->watchdog, sch);
|
||||
|
||||
if (opt) {
|
||||
- int err = cake_change(sch, opt, extack);
|
||||
+ err = cake_change(sch, opt, extack);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
@@ -3030,7 +3030,7 @@ static int cake_dump_class_stats(struct
|
||||
PUT_STAT_S32(BLUE_TIMER_US,
|
||||
ktime_to_us(
|
||||
ktime_sub(now,
|
||||
- flow->cvars.blue_timer)));
|
||||
+ flow->cvars.blue_timer)));
|
||||
}
|
||||
if (flow->cvars.dropping) {
|
||||
PUT_STAT_S32(DROP_NEXT_US,
|
||||
@ -0,0 +1,57 @@
|
||||
From b8392808eb3fc28e523e28cb258c81ca246deb9b Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
Date: Thu, 25 Jun 2020 22:18:00 +0200
|
||||
Subject: [PATCH] sch_cake: add RFC 8622 LE PHB support to CAKE diffserv
|
||||
handling
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Change tin mapping on diffserv3, 4 & 8 for LE PHB support, in essence
|
||||
making LE a member of the Bulk tin.
|
||||
|
||||
Bulk has the least priority and minimum of 1/16th total bandwidth in the
|
||||
face of higher priority traffic.
|
||||
|
||||
NB: Diffserv 3 & 4 swap tin 0 & 1 priorities from the default order as
|
||||
found in diffserv8, in case anyone is wondering why it looks a bit odd.
|
||||
|
||||
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
[ reword commit message slightly ]
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
net/sched/sch_cake.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -312,8 +312,8 @@ static const u8 precedence[] = {
|
||||
};
|
||||
|
||||
static const u8 diffserv8[] = {
|
||||
- 2, 5, 1, 2, 4, 2, 2, 2,
|
||||
- 0, 2, 1, 2, 1, 2, 1, 2,
|
||||
+ 2, 0, 1, 2, 4, 2, 2, 2,
|
||||
+ 1, 2, 1, 2, 1, 2, 1, 2,
|
||||
5, 2, 4, 2, 4, 2, 4, 2,
|
||||
3, 2, 3, 2, 3, 2, 3, 2,
|
||||
6, 2, 3, 2, 3, 2, 3, 2,
|
||||
@@ -323,7 +323,7 @@ static const u8 diffserv8[] = {
|
||||
};
|
||||
|
||||
static const u8 diffserv4[] = {
|
||||
- 0, 2, 0, 0, 2, 0, 0, 0,
|
||||
+ 0, 1, 0, 0, 2, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 2, 0, 2, 0, 2, 0,
|
||||
2, 0, 2, 0, 2, 0, 2, 0,
|
||||
@@ -334,7 +334,7 @@ static const u8 diffserv4[] = {
|
||||
};
|
||||
|
||||
static const u8 diffserv3[] = {
|
||||
- 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
+ 0, 1, 0, 0, 2, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -55,7 +55,7 @@ Cc: Kir Kolyshkin <kir@openvz.org>
|
||||
rwlock_t sk_callback_lock;
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -2484,6 +2484,7 @@ void sock_init_data(struct socket *sock,
|
||||
@@ -2486,6 +2486,7 @@ void sock_init_data(struct socket *sock,
|
||||
|
||||
sk->sk_max_pacing_rate = ~0U;
|
||||
sk->sk_pacing_rate = ~0U;
|
||||
|
||||
@ -24,7 +24,7 @@ Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -928,6 +928,7 @@ static inline void nand_set_controller_d
|
||||
@@ -926,6 +926,7 @@ static inline void nand_set_controller_d
|
||||
#define NAND_MFR_SANDISK 0x45
|
||||
#define NAND_MFR_INTEL 0x89
|
||||
#define NAND_MFR_ATO 0x9b
|
||||
|
||||
@ -4367,6 +4367,7 @@ CONFIG_SERIAL_EARLYCON=y
|
||||
# CONFIG_SG_POOL is not set
|
||||
# CONFIG_SG_SPLIT is not set
|
||||
CONFIG_SHMEM=y
|
||||
# CONFIG_SHORTCUT_FE is not set
|
||||
# CONFIG_SH_ETH is not set
|
||||
# CONFIG_SH_TIMER_CMT is not set
|
||||
# CONFIG_SH_TIMER_MTU2 is not set
|
||||
|
||||
@ -4592,6 +4592,7 @@ CONFIG_SERIAL_EARLYCON=y
|
||||
# CONFIG_SG_POOL is not set
|
||||
# CONFIG_SG_SPLIT is not set
|
||||
CONFIG_SHMEM=y
|
||||
# CONFIG_SHORTCUT_FE is not set
|
||||
# CONFIG_SH_ETH is not set
|
||||
# CONFIG_SH_TIMER_CMT is not set
|
||||
# CONFIG_SH_TIMER_MTU2 is not set
|
||||
|
||||
@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
EXPORT_SYMBOL(default_qdisc_ops);
|
||||
|
||||
/* Main transmission queue. */
|
||||
@@ -772,7 +772,7 @@ static void attach_one_default_qdisc(str
|
||||
@@ -773,7 +773,7 @@ static void attach_one_default_qdisc(str
|
||||
void *_unused)
|
||||
{
|
||||
struct Qdisc *qdisc;
|
||||
|
||||
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/sched/sch_generic.c
|
||||
+++ b/net/sched/sch_generic.c
|
||||
@@ -461,146 +461,6 @@ struct Qdisc_ops noqueue_qdisc_ops __rea
|
||||
@@ -462,146 +462,6 @@ struct Qdisc_ops noqueue_qdisc_ops __rea
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
|
||||
{
|
||||
struct dst_entry *dst = __sk_dst_get(sk);
|
||||
@@ -1598,9 +1610,11 @@ void sk_destruct(struct sock *sk)
|
||||
@@ -1599,9 +1611,11 @@ void sk_destruct(struct sock *sk)
|
||||
|
||||
static void __sk_free(struct sock *sk)
|
||||
{
|
||||
|
||||
@ -327,7 +327,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -3387,6 +3387,8 @@ static __net_initdata struct pernet_oper
|
||||
@@ -3389,6 +3389,8 @@ static __net_initdata struct pernet_oper
|
||||
|
||||
static int __init proto_init(void)
|
||||
{
|
||||
|
||||
@ -0,0 +1,236 @@
|
||||
--- a/include/linux/skbuff.h 2019-01-16 20:16:08.325745306 +0800
|
||||
+++ b/include/linux/skbuff.h 2019-01-16 20:31:47.288028493 +0800
|
||||
@@ -783,6 +783,9 @@ struct sk_buff {
|
||||
__u8 tc_from_ingress:1;
|
||||
#endif
|
||||
__u8 gro_skip:1;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ __u8 fast_forwarded:1;
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_NET_SCHED
|
||||
__u16 tc_index; /* traffic control index */
|
||||
--- a/include/linux/if_bridge.h 2019-01-16 20:51:47.871445535 +0800
|
||||
+++ b/include/linux/if_bridge.h 2019-01-16 20:52:26.220269649 +0800
|
||||
@@ -54,6 +54,8 @@ struct br_ip_list {
|
||||
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
|
||||
|
||||
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
|
||||
+extern void br_dev_update_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *nlstats);
|
||||
|
||||
typedef int br_should_route_hook_t(struct sk_buff *skb);
|
||||
extern br_should_route_hook_t __rcu *br_should_route_hook;
|
||||
--- a/include/linux/timer.h
|
||||
+++ b/include/linux/timer.h
|
||||
@@ -20,6 +20,9 @@ struct timer_list {
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
u32 flags;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ unsigned long cust_data;
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
struct lockdep_map lockdep_map;
|
||||
--- a/net/Kconfig 2019-01-16 20:36:30.266465286 +0800
|
||||
+++ b/net/Kconfig 2019-01-16 20:36:41.980609067 +0800
|
||||
@@ -463,3 +463,6 @@ config HAVE_CBPF_JIT
|
||||
# Extended BPF JIT (eBPF)
|
||||
config HAVE_EBPF_JIT
|
||||
bool
|
||||
+
|
||||
+config SHORTCUT_FE
|
||||
+ bool "Enables kernel network stack path for Shortcut Forwarding Engine
|
||||
--- a/net/core/dev.c 2019-01-16 20:38:37.274933833 +0800
|
||||
+++ b/net/core/dev.c 2019-01-16 20:44:07.773594898 +0800
|
||||
@@ -3001,8 +3001,17 @@ static int xmit_one(struct sk_buff *skb,
|
||||
unsigned int len;
|
||||
int rc;
|
||||
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ /* If this skb has been fast forwarded then we don't want it to
|
||||
+ * go to any taps (by definition we're trying to bypass them).
|
||||
+ */
|
||||
+ if (!skb->fast_forwarded) {
|
||||
+#endif
|
||||
if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_ETHERNET_PACKET_MANGLE
|
||||
if (!dev->eth_mangle_tx ||
|
||||
@@ -4315,6 +4324,11 @@ void netdev_rx_handler_unregister(struct
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
|
||||
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Limit the use of PFMEMALLOC reserves to those protocols that implement
|
||||
* the special handling of PFMEMALLOC skbs.
|
||||
@@ -4362,6 +4376,9 @@ static int __netif_receive_skb_core(stru
|
||||
bool deliver_exact = false;
|
||||
int ret = NET_RX_DROP;
|
||||
__be16 type;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ int (*fast_recv)(struct sk_buff *skb);
|
||||
+#endif
|
||||
|
||||
net_timestamp_check(!netdev_tstamp_prequeue, skb);
|
||||
|
||||
@@ -4388,6 +4405,16 @@ another_round:
|
||||
goto out;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ fast_recv = rcu_dereference(athrs_fast_nat_recv);
|
||||
+ if (fast_recv) {
|
||||
+ if (fast_recv(skb)) {
|
||||
+ ret = NET_RX_SUCCESS;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (skb_skip_tc_classify(skb))
|
||||
goto skip_classify;
|
||||
|
||||
--- a/net/netfilter/nf_conntrack_proto_tcp.c 2019-01-16 20:47:40.886993297 +0800
|
||||
+++ b/net/netfilter/nf_conntrack_proto_tcp.c 2019-01-16 20:48:57.700570104 +0800
|
||||
@@ -35,11 +35,17 @@
|
||||
|
||||
/* Do not check the TCP window for incoming packets */
|
||||
static int nf_ct_tcp_no_window_check __read_mostly = 1;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+EXPORT_SYMBOL_GPL(nf_ct_tcp_no_window_check);
|
||||
+#endif
|
||||
|
||||
/* "Be conservative in what you do,
|
||||
be liberal in what you accept from others."
|
||||
If it's non-zero, we mark only out of window RST segments as INVALID. */
|
||||
static int nf_ct_tcp_be_liberal __read_mostly = 0;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+EXPORT_SYMBOL_GPL(nf_ct_tcp_be_liberal);
|
||||
+#endif
|
||||
|
||||
/* If it is set to zero, we disable picking up already established
|
||||
connections. */
|
||||
--- a/net/bridge/br_if.c 2019-01-16 20:54:51.919367044 +0800
|
||||
+++ b/net/bridge/br_if.c 2019-01-16 20:55:53.812401263 +0800
|
||||
@@ -653,3 +653,26 @@ void br_port_flags_change(struct net_bri
|
||||
if (mask & BR_AUTO_MASK)
|
||||
nbp_update_port_count(br);
|
||||
}
|
||||
+
|
||||
+/* Update bridge statistics for bridge packets processed by offload engines */
|
||||
+void br_dev_update_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *nlstats)
|
||||
+{
|
||||
+ struct net_bridge *br;
|
||||
+ struct pcpu_sw_netstats *stats;
|
||||
+
|
||||
+ /* Is this a bridge? */
|
||||
+ if (!(dev->priv_flags & IFF_EBRIDGE))
|
||||
+ return;
|
||||
+
|
||||
+ br = netdev_priv(dev);
|
||||
+ stats = this_cpu_ptr(br->stats);
|
||||
+
|
||||
+ u64_stats_update_begin(&stats->syncp);
|
||||
+ stats->rx_packets += nlstats->rx_packets;
|
||||
+ stats->rx_bytes += nlstats->rx_bytes;
|
||||
+ stats->tx_packets += nlstats->tx_packets;
|
||||
+ stats->tx_bytes += nlstats->tx_bytes;
|
||||
+ u64_stats_update_end(&stats->syncp);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_dev_update_stats);
|
||||
--- a/net/netfilter/Kconfig 2019-01-16 21:07:34.543460920 +0800
|
||||
+++ b/net/netfilter/Kconfig 2019-01-16 21:08:14.739465937 +0800
|
||||
@@ -146,6 +146,14 @@ config NF_CONNTRACK_TIMEOUT
|
||||
|
||||
If unsure, say `N'.
|
||||
|
||||
+config NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ bool "Register multiple callbacks to ct events"
|
||||
+ depends on NF_CONNTRACK_EVENTS
|
||||
+ help
|
||||
+ Support multiple registrations.
|
||||
+
|
||||
+ If unsure, say `N'.
|
||||
+
|
||||
config NF_CONNTRACK_TIMESTAMP
|
||||
bool 'Connection tracking timestamping'
|
||||
depends on NETFILTER_ADVANCED
|
||||
--- a/net/netfilter/nf_conntrack_ecache.c 2019-01-16 21:12:22.183462975 +0800
|
||||
+++ b/net/netfilter/nf_conntrack_ecache.c 2019-01-16 21:26:10.379462031 +0800
|
||||
@@ -122,13 +125,17 @@ int nf_conntrack_eventmask_report(unsign
|
||||
{
|
||||
int ret = 0;
|
||||
struct net *net = nf_ct_net(ct);
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
struct nf_ct_event_notifier *notify;
|
||||
+#endif
|
||||
struct nf_conntrack_ecache *e;
|
||||
|
||||
rcu_read_lock();
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
|
||||
if (!notify)
|
||||
goto out_unlock;
|
||||
+#endif
|
||||
|
||||
e = nf_ct_ecache_find(ct);
|
||||
if (!e)
|
||||
@@ -146,7 +153,12 @@ int nf_conntrack_eventmask_report(unsign
|
||||
if (!((eventmask | missed) & e->ctmask))
|
||||
goto out_unlock;
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
|
||||
+ eventmask | missed, &item);
|
||||
+#else
|
||||
ret = notify->fcn(eventmask | missed, &item);
|
||||
+#endif
|
||||
if (unlikely(ret < 0 || missed)) {
|
||||
spin_lock_bh(&ct->lock);
|
||||
if (ret < 0) {
|
||||
@@ -179,15 +191,19 @@ void nf_ct_deliver_cached_events(struct
|
||||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
unsigned long events, missed;
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
struct nf_ct_event_notifier *notify;
|
||||
+#endif
|
||||
struct nf_conntrack_ecache *e;
|
||||
struct nf_ct_event item;
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
|
||||
if (notify == NULL)
|
||||
goto out_unlock;
|
||||
+#endif
|
||||
|
||||
e = nf_ct_ecache_find(ct);
|
||||
if (e == NULL)
|
||||
@@ -210,7 +226,13 @@ void nf_ct_deliver_cached_events(struct
|
||||
item.portid = 0;
|
||||
item.report = 0;
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
|
||||
+ events | missed,
|
||||
+ &item);
|
||||
+#else
|
||||
ret = notify->fcn(events | missed, &item);
|
||||
+#endif
|
||||
|
||||
if (likely(ret == 0 && !missed))
|
||||
goto out_unlock;
|
||||
@ -0,0 +1,114 @@
|
||||
From a00590d570212c3c633bd463cef8ec7377cc7993 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
Date: Tue, 30 Jun 2020 12:07:44 +0100
|
||||
Subject: [PATCH] sch_cake: fix IP protocol handling in the presence of VLAN
|
||||
tags
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
From: Ilya Ponetayev <i.ponetaev@ndmsystems.com>
|
||||
|
||||
CAKE was using the return value of tc_skb_protocol() and expecting it to be
|
||||
the IP protocol type. This can fail in the presence of QinQ VLAN tags,
|
||||
making CAKE unable to handle ECN marking and diffserv parsing in this case.
|
||||
Fix this by implementing our own version of tc_skb_protocol(), which will
|
||||
use skb->protocol directly, but also parse and skip over any VLAN tags and
|
||||
return the inner protocol number instead.
|
||||
|
||||
Also fix CE marking by implementing a version of INET_ECN_set_ce() that
|
||||
uses the same parsing routine.
|
||||
|
||||
Fixes: ea82511518f4 ("sch_cake: Add NAT awareness to packet classifier")
|
||||
Fixes: b2100cc56fca ("sch_cake: Use tc_skb_protocol() helper for getting packet protocol")
|
||||
Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
|
||||
Signed-off-by: Ilya Ponetayev <i.ponetaev@ndmsystems.com>
|
||||
[ squash original two patches, rewrite commit message ]
|
||||
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
|
||||
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
|
||||
---
|
||||
net/sched/sch_cake.c | 52 +++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 49 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/net/sched/sch_cake.c
|
||||
+++ b/net/sched/sch_cake.c
|
||||
@@ -497,6 +497,52 @@ static bool cobalt_queue_empty(struct co
|
||||
return down;
|
||||
}
|
||||
|
||||
+static __be16 cake_skb_proto(const struct sk_buff *skb)
|
||||
+{
|
||||
+ unsigned int offset = skb_mac_offset(skb) + sizeof(struct ethhdr);
|
||||
+ __be16 proto = skb->protocol;
|
||||
+ struct vlan_hdr vhdr, *vh;
|
||||
+
|
||||
+ while (proto == htons(ETH_P_8021Q) || proto == htons(ETH_P_8021AD)) {
|
||||
+ vh = skb_header_pointer(skb, offset, sizeof(vhdr), &vhdr);
|
||||
+ if (!vh)
|
||||
+ break;
|
||||
+
|
||||
+ proto = vh->h_vlan_encapsulated_proto;
|
||||
+ offset += sizeof(vhdr);
|
||||
+ }
|
||||
+
|
||||
+ return proto;
|
||||
+}
|
||||
+
|
||||
+static int cake_set_ce(struct sk_buff *skb)
|
||||
+{
|
||||
+ int wlen = skb_network_offset(skb);
|
||||
+
|
||||
+ switch (cake_skb_proto(skb)) {
|
||||
+ case htons(ETH_P_IP):
|
||||
+ wlen += sizeof(struct iphdr);
|
||||
+ if (!pskb_may_pull(skb, wlen) ||
|
||||
+ skb_try_make_writable(skb, wlen))
|
||||
+ return 0;
|
||||
+
|
||||
+ return IP_ECN_set_ce(ip_hdr(skb));
|
||||
+
|
||||
+ case htons(ETH_P_IPV6):
|
||||
+ wlen += sizeof(struct ipv6hdr);
|
||||
+ if (!pskb_may_pull(skb, wlen) ||
|
||||
+ skb_try_make_writable(skb, wlen))
|
||||
+ return 0;
|
||||
+
|
||||
+ return IP6_ECN_set_ce(skb, ipv6_hdr(skb));
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Call this with a freshly dequeued packet for possible congestion marking.
|
||||
* Returns true as an instruction to drop the packet, false for delivery.
|
||||
*/
|
||||
@@ -549,7 +595,7 @@ static bool cobalt_should_drop(struct co
|
||||
|
||||
if (next_due && vars->dropping) {
|
||||
/* Use ECN mark if possible, otherwise drop */
|
||||
- drop = !(vars->ecn_marked = INET_ECN_set_ce(skb));
|
||||
+ drop = !(vars->ecn_marked = cake_set_ce(skb));
|
||||
|
||||
vars->count++;
|
||||
if (!vars->count)
|
||||
@@ -592,7 +638,7 @@ static bool cake_update_flowkeys(struct
|
||||
bool rev = !skb->_nfct, upd = false;
|
||||
__be32 ip;
|
||||
|
||||
- if (tc_skb_protocol(skb) != htons(ETH_P_IP))
|
||||
+ if (cake_skb_proto(skb) != htons(ETH_P_IP))
|
||||
return false;
|
||||
|
||||
if (!nf_ct_get_tuple_skb(&tuple, skb))
|
||||
@@ -1557,7 +1603,7 @@ static u8 cake_handle_diffserv(struct sk
|
||||
u16 *buf, buf_;
|
||||
u8 dscp;
|
||||
|
||||
- switch (tc_skb_protocol(skb)) {
|
||||
+ switch (cake_skb_proto(skb)) {
|
||||
case htons(ETH_P_IP):
|
||||
buf = skb_header_pointer(skb, offset, sizeof(buf_), &buf_);
|
||||
if (unlikely(!buf))
|
||||
@ -0,0 +1,236 @@
|
||||
--- a/include/linux/skbuff.h 2019-01-16 20:16:08.325745306 +0800
|
||||
+++ b/include/linux/skbuff.h 2019-01-16 20:31:47.288028493 +0800
|
||||
@@ -783,6 +783,9 @@ struct sk_buff {
|
||||
__u8 tc_from_ingress:1;
|
||||
#endif
|
||||
__u8 gro_skip:1;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ __u8 fast_forwarded:1;
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_NET_SCHED
|
||||
__u16 tc_index; /* traffic control index */
|
||||
--- a/include/linux/if_bridge.h 2019-01-16 20:51:47.871445535 +0800
|
||||
+++ b/include/linux/if_bridge.h 2019-01-16 20:52:26.220269649 +0800
|
||||
@@ -54,6 +54,8 @@ struct br_ip_list {
|
||||
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
|
||||
|
||||
extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
|
||||
+extern void br_dev_update_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *nlstats);
|
||||
|
||||
typedef int br_should_route_hook_t(struct sk_buff *skb);
|
||||
extern br_should_route_hook_t __rcu *br_should_route_hook;
|
||||
--- a/include/linux/timer.h
|
||||
+++ b/include/linux/timer.h
|
||||
@@ -20,6 +20,9 @@ struct timer_list {
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
u32 flags;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ unsigned long cust_data;
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
struct lockdep_map lockdep_map;
|
||||
--- a/net/Kconfig 2019-01-16 20:36:30.266465286 +0800
|
||||
+++ b/net/Kconfig 2019-01-16 20:36:41.980609067 +0800
|
||||
@@ -463,3 +463,6 @@ config HAVE_CBPF_JIT
|
||||
# Extended BPF JIT (eBPF)
|
||||
config HAVE_EBPF_JIT
|
||||
bool
|
||||
+
|
||||
+config SHORTCUT_FE
|
||||
+ bool "Enables kernel network stack path for Shortcut Forwarding Engine
|
||||
--- a/net/core/dev.c 2019-01-16 20:38:37.274933833 +0800
|
||||
+++ b/net/core/dev.c 2019-01-16 20:44:07.773594898 +0800
|
||||
@@ -3001,8 +3001,17 @@ static int xmit_one(struct sk_buff *skb,
|
||||
unsigned int len;
|
||||
int rc;
|
||||
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ /* If this skb has been fast forwarded then we don't want it to
|
||||
+ * go to any taps (by definition we're trying to bypass them).
|
||||
+ */
|
||||
+ if (!skb->fast_forwarded) {
|
||||
+#endif
|
||||
if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all))
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_ETHERNET_PACKET_MANGLE
|
||||
if (!dev->eth_mangle_tx ||
|
||||
@@ -4315,6 +4324,11 @@ void netdev_rx_handler_unregister(struct
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
|
||||
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Limit the use of PFMEMALLOC reserves to those protocols that implement
|
||||
* the special handling of PFMEMALLOC skbs.
|
||||
@@ -4362,6 +4376,9 @@ static int __netif_receive_skb_core(stru
|
||||
bool deliver_exact = false;
|
||||
int ret = NET_RX_DROP;
|
||||
__be16 type;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ int (*fast_recv)(struct sk_buff *skb);
|
||||
+#endif
|
||||
|
||||
net_timestamp_check(!netdev_tstamp_prequeue, skb);
|
||||
|
||||
@@ -4388,6 +4405,16 @@ another_round:
|
||||
goto out;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+ fast_recv = rcu_dereference(athrs_fast_nat_recv);
|
||||
+ if (fast_recv) {
|
||||
+ if (fast_recv(skb)) {
|
||||
+ ret = NET_RX_SUCCESS;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
if (skb_skip_tc_classify(skb))
|
||||
goto skip_classify;
|
||||
|
||||
--- a/net/netfilter/nf_conntrack_proto_tcp.c 2019-01-16 20:47:40.886993297 +0800
|
||||
+++ b/net/netfilter/nf_conntrack_proto_tcp.c 2019-01-16 20:48:57.700570104 +0800
|
||||
@@ -35,11 +35,17 @@
|
||||
|
||||
/* Do not check the TCP window for incoming packets */
|
||||
static int nf_ct_tcp_no_window_check __read_mostly = 1;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+EXPORT_SYMBOL_GPL(nf_ct_tcp_no_window_check);
|
||||
+#endif
|
||||
|
||||
/* "Be conservative in what you do,
|
||||
be liberal in what you accept from others."
|
||||
If it's non-zero, we mark only out of window RST segments as INVALID. */
|
||||
static int nf_ct_tcp_be_liberal __read_mostly = 0;
|
||||
+#ifdef CONFIG_SHORTCUT_FE
|
||||
+EXPORT_SYMBOL_GPL(nf_ct_tcp_be_liberal);
|
||||
+#endif
|
||||
|
||||
/* If it is set to zero, we disable picking up already established
|
||||
connections. */
|
||||
--- a/net/bridge/br_if.c 2019-01-16 20:54:51.919367044 +0800
|
||||
+++ b/net/bridge/br_if.c 2019-01-16 20:55:53.812401263 +0800
|
||||
@@ -653,3 +653,26 @@ void br_port_flags_change(struct net_bri
|
||||
if (mask & BR_AUTO_MASK)
|
||||
nbp_update_port_count(br);
|
||||
}
|
||||
+
|
||||
+/* Update bridge statistics for bridge packets processed by offload engines */
|
||||
+void br_dev_update_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *nlstats)
|
||||
+{
|
||||
+ struct net_bridge *br;
|
||||
+ struct pcpu_sw_netstats *stats;
|
||||
+
|
||||
+ /* Is this a bridge? */
|
||||
+ if (!(dev->priv_flags & IFF_EBRIDGE))
|
||||
+ return;
|
||||
+
|
||||
+ br = netdev_priv(dev);
|
||||
+ stats = this_cpu_ptr(br->stats);
|
||||
+
|
||||
+ u64_stats_update_begin(&stats->syncp);
|
||||
+ stats->rx_packets += nlstats->rx_packets;
|
||||
+ stats->rx_bytes += nlstats->rx_bytes;
|
||||
+ stats->tx_packets += nlstats->tx_packets;
|
||||
+ stats->tx_bytes += nlstats->tx_bytes;
|
||||
+ u64_stats_update_end(&stats->syncp);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_dev_update_stats);
|
||||
--- a/net/netfilter/Kconfig 2019-01-16 21:07:34.543460920 +0800
|
||||
+++ b/net/netfilter/Kconfig 2019-01-16 21:08:14.739465937 +0800
|
||||
@@ -146,6 +146,14 @@ config NF_CONNTRACK_TIMEOUT
|
||||
|
||||
If unsure, say `N'.
|
||||
|
||||
+config NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ bool "Register multiple callbacks to ct events"
|
||||
+ depends on NF_CONNTRACK_EVENTS
|
||||
+ help
|
||||
+ Support multiple registrations.
|
||||
+
|
||||
+ If unsure, say `N'.
|
||||
+
|
||||
config NF_CONNTRACK_TIMESTAMP
|
||||
bool 'Connection tracking timestamping'
|
||||
depends on NETFILTER_ADVANCED
|
||||
--- a/net/netfilter/nf_conntrack_ecache.c 2019-01-16 21:12:22.183462975 +0800
|
||||
+++ b/net/netfilter/nf_conntrack_ecache.c 2019-01-16 21:26:10.379462031 +0800
|
||||
@@ -122,13 +125,17 @@ int nf_conntrack_eventmask_report(unsign
|
||||
{
|
||||
int ret = 0;
|
||||
struct net *net = nf_ct_net(ct);
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
struct nf_ct_event_notifier *notify;
|
||||
+#endif
|
||||
struct nf_conntrack_ecache *e;
|
||||
|
||||
rcu_read_lock();
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
|
||||
if (!notify)
|
||||
goto out_unlock;
|
||||
+#endif
|
||||
|
||||
e = nf_ct_ecache_find(ct);
|
||||
if (!e)
|
||||
@@ -146,7 +153,12 @@ int nf_conntrack_eventmask_report(unsign
|
||||
if (!((eventmask | missed) & e->ctmask))
|
||||
goto out_unlock;
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
|
||||
+ eventmask | missed, &item);
|
||||
+#else
|
||||
ret = notify->fcn(eventmask | missed, &item);
|
||||
+#endif
|
||||
if (unlikely(ret < 0 || missed)) {
|
||||
spin_lock_bh(&ct->lock);
|
||||
if (ret < 0) {
|
||||
@@ -179,15 +191,19 @@ void nf_ct_deliver_cached_events(struct
|
||||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
unsigned long events, missed;
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
struct nf_ct_event_notifier *notify;
|
||||
+#endif
|
||||
struct nf_conntrack_ecache *e;
|
||||
struct nf_ct_event item;
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
|
||||
if (notify == NULL)
|
||||
goto out_unlock;
|
||||
+#endif
|
||||
|
||||
e = nf_ct_ecache_find(ct);
|
||||
if (e == NULL)
|
||||
@@ -210,7 +226,13 @@ void nf_ct_deliver_cached_events(struct
|
||||
item.portid = 0;
|
||||
item.report = 0;
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
|
||||
+ events | missed,
|
||||
+ &item);
|
||||
+#else
|
||||
ret = notify->fcn(events | missed, &item);
|
||||
+#endif
|
||||
|
||||
if (likely(ret == 0 && !missed))
|
||||
goto out_unlock;
|
||||
@ -43,7 +43,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
algorithm registration.
|
||||
--- a/crypto/algboss.c
|
||||
+++ b/crypto/algboss.c
|
||||
@@ -248,12 +248,16 @@ static int cryptomgr_schedule_test(struc
|
||||
@@ -246,12 +246,16 @@ static int cryptomgr_schedule_test(struc
|
||||
type = alg->cra_flags;
|
||||
|
||||
/* This piece of crap needs to disappear into per-type test hooks. */
|
||||
|
||||
@ -83,7 +83,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
EXPORT_SYMBOL(default_qdisc_ops);
|
||||
|
||||
/* Main transmission queue. */
|
||||
@@ -772,7 +772,7 @@ static void attach_one_default_qdisc(str
|
||||
@@ -773,7 +773,7 @@ static void attach_one_default_qdisc(str
|
||||
void *_unused)
|
||||
{
|
||||
struct Qdisc *qdisc;
|
||||
|
||||
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/sched/sch_generic.c
|
||||
+++ b/net/sched/sch_generic.c
|
||||
@@ -457,146 +457,6 @@ struct Qdisc_ops noqueue_qdisc_ops __rea
|
||||
@@ -458,146 +458,6 @@ struct Qdisc_ops noqueue_qdisc_ops __rea
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
help
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -2980,10 +2980,20 @@ static int xmit_one(struct sk_buff *skb,
|
||||
@@ -2976,10 +2976,20 @@ static int xmit_one(struct sk_buff *skb,
|
||||
#endif
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
obj-$(CONFIG_PROC_FS) += net-procfs.o
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -1463,9 +1463,11 @@ void sk_destruct(struct sock *sk)
|
||||
@@ -1464,9 +1464,11 @@ void sk_destruct(struct sock *sk)
|
||||
|
||||
static void __sk_free(struct sock *sk)
|
||||
{
|
||||
|
||||
@ -328,7 +328,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
--- a/net/core/sock.c
|
||||
+++ b/net/core/sock.c
|
||||
@@ -3093,6 +3093,8 @@ static __net_initdata struct pernet_oper
|
||||
@@ -3095,6 +3095,8 @@ static __net_initdata struct pernet_oper
|
||||
|
||||
static int __init proto_init(void)
|
||||
{
|
||||
|
||||
@ -1592,7 +1592,7 @@
|
||||
* number or errno values. Not nice, but better than additional function
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -141,6 +141,9 @@
|
||||
@@ -142,6 +142,9 @@
|
||||
#include <linux/netfilter_ingress.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/crash_dump.h>
|
||||
@ -1602,7 +1602,7 @@
|
||||
|
||||
#include "net-sysfs.h"
|
||||
|
||||
@@ -2969,7 +2972,12 @@ static int xmit_one(struct sk_buff *skb,
|
||||
@@ -2965,7 +2968,12 @@ static int xmit_one(struct sk_buff *skb,
|
||||
unsigned int len;
|
||||
int rc;
|
||||
|
||||
@ -1615,7 +1615,7 @@
|
||||
dev_queue_xmit_nit(skb, dev);
|
||||
|
||||
len = skb->len;
|
||||
@@ -3008,6 +3016,8 @@ out:
|
||||
@@ -3004,6 +3012,8 @@ out:
|
||||
return skb;
|
||||
}
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
__u8 imq_flags:IMQ_F_BITS;
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -4582,6 +4582,9 @@ static enum gro_result dev_gro_receive(s
|
||||
@@ -4578,6 +4578,9 @@ static enum gro_result dev_gro_receive(s
|
||||
enum gro_result ret;
|
||||
int grow;
|
||||
|
||||
@ -44,7 +44,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
if (!(skb->dev->features & NETIF_F_GRO))
|
||||
goto normal;
|
||||
|
||||
@@ -5877,6 +5880,48 @@ static void __netdev_adjacent_dev_unlink
|
||||
@@ -5873,6 +5876,48 @@ static void __netdev_adjacent_dev_unlink
|
||||
&upper_dev->adj_list.lower);
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static int __netdev_upper_dev_link(struct net_device *dev,
|
||||
struct net_device *upper_dev, bool master,
|
||||
void *upper_priv, void *upper_info)
|
||||
@@ -5949,6 +5994,7 @@ static int __netdev_upper_dev_link(struc
|
||||
@@ -5945,6 +5990,7 @@ static int __netdev_upper_dev_link(struc
|
||||
goto rollback_lower_mesh;
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
|
||||
&changeupper_info.info);
|
||||
ret = notifier_to_errno(ret);
|
||||
@@ -6075,6 +6121,7 @@ void netdev_upper_dev_unlink(struct net_
|
||||
@@ -6071,6 +6117,7 @@ void netdev_upper_dev_unlink(struct net_
|
||||
list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
|
||||
__netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr);
|
||||
|
||||
@ -109,7 +109,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
|
||||
&changeupper_info.info);
|
||||
}
|
||||
@@ -6678,6 +6725,7 @@ int dev_set_mac_address(struct net_devic
|
||||
@@ -6674,6 +6721,7 @@ int dev_set_mac_address(struct net_devic
|
||||
if (err)
|
||||
return err;
|
||||
dev->addr_assign_type = NET_ADDR_SET;
|
||||
|
||||
@ -45,7 +45,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
depends on ACPI
|
||||
--- a/drivers/ata/libata-core.c
|
||||
+++ b/drivers/ata/libata-core.c
|
||||
@@ -731,6 +731,19 @@ u64 ata_tf_read_block(const struct ata_t
|
||||
@@ -730,6 +730,19 @@ u64 ata_tf_read_block(const struct ata_t
|
||||
return block;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
/**
|
||||
* ata_build_rw_tf - Build ATA taskfile for given read/write request
|
||||
* @tf: Target ATA taskfile
|
||||
@@ -4998,6 +5011,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
|
||||
@@ -4997,6 +5010,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
|
||||
if (tag < 0)
|
||||
return NULL;
|
||||
}
|
||||
@ -75,7 +75,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
qc = __ata_qc_from_tag(ap, tag);
|
||||
qc->tag = tag;
|
||||
@@ -5899,6 +5915,9 @@ struct ata_port *ata_port_alloc(struct a
|
||||
@@ -5898,6 +5914,9 @@ struct ata_port *ata_port_alloc(struct a
|
||||
ap->stats.unhandled_irq = 1;
|
||||
ap->stats.idle_irq = 1;
|
||||
#endif
|
||||
@ -85,7 +85,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
ata_sff_port_init(ap);
|
||||
|
||||
return ap;
|
||||
@@ -5920,6 +5939,12 @@ static void ata_host_release(struct devi
|
||||
@@ -5919,6 +5938,12 @@ static void ata_host_release(struct devi
|
||||
|
||||
kfree(ap->pmp_link);
|
||||
kfree(ap->slave_link);
|
||||
@ -98,7 +98,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
kfree(ap);
|
||||
host->ports[i] = NULL;
|
||||
}
|
||||
@@ -6366,7 +6391,23 @@ int ata_host_register(struct ata_host *h
|
||||
@@ -6365,7 +6390,23 @@ int ata_host_register(struct ata_host *h
|
||||
host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
|
||||
host->ports[i]->local_port_no = i + 1;
|
||||
}
|
||||
@ -124,17 +124,17 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
rc = ata_tport_add(host->dev,host->ports[i]);
|
||||
--- a/include/linux/libata.h
|
||||
+++ b/include/linux/libata.h
|
||||
@@ -38,6 +38,9 @@
|
||||
#include <linux/acpi.h>
|
||||
@@ -39,6 +39,9 @@
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/async.h>
|
||||
+#ifdef CONFIG_ATA_LEDS
|
||||
+#include <linux/leds.h>
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* Define if arch has non-standard setup. This is a _PCI_ standard
|
||||
@@ -884,6 +887,12 @@ struct ata_port {
|
||||
@@ -887,6 +890,12 @@ struct ata_port {
|
||||
#ifdef CONFIG_ATA_ACPI
|
||||
struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
|
||||
#endif
|
||||
|
||||
@ -20,6 +20,6 @@ DEFAULT_PACKAGES += \
|
||||
kmod-usb3 kmod-usb-dwc3 ath10k-firmware-qca4019 \
|
||||
automount autosamba luci-app-ipsec-vpnd v2ray shadowsocks-libev-ss-redir shadowsocksr-libev-server \
|
||||
luci-app-unblockmusic luci-app-cpufreq luci-app-zerotier ca-certificates \
|
||||
htop fdisk e2fsprogs
|
||||
htop fdisk e2fsprogs ethtool
|
||||
|
||||
$(eval $(call BuildTarget))
|
||||
|
||||
@ -229,7 +229,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
|
||||
mtk->num_phys = of_count_phandle_with_args(node,
|
||||
"phys", "#phy-cells");
|
||||
@@ -782,7 +725,7 @@ static int __maybe_unused xhci_mtk_suspe
|
||||
@@ -783,7 +726,7 @@ static int __maybe_unused xhci_mtk_suspe
|
||||
xhci_mtk_host_disable(mtk);
|
||||
xhci_mtk_phy_power_off(mtk);
|
||||
xhci_mtk_clks_disable(mtk);
|
||||
@ -238,7 +238,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -792,7 +735,7 @@ static int __maybe_unused xhci_mtk_resum
|
||||
@@ -793,7 +736,7 @@ static int __maybe_unused xhci_mtk_resum
|
||||
struct usb_hcd *hcd = mtk->hcd;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
|
||||
|
||||
@ -21,9 +21,8 @@ include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
DEFAULT_PACKAGES += partx-utils mkf2fs fdisk e2fsprogs wpad kmod-usb-hid kmod-ath5k kmod-ath9k kmod-ath9k-htc kmod-ath10k \
|
||||
kmod-rt2800-usb kmod-e1000e kmod-igb kmod-igbvf kmod-ixgbe kmod-pcnet32 kmod-tulip kmod-vmxnet3 kmod-i40e kmod-i40evf kmod-r8125 kmod-r8168 kmod-8139cp kmod-8139too kmod-fs-f2fs \
|
||||
htop lm-sensors autocore-x86 automount autosamba luci-app-ipsec-vpnd luci-proto-bonding luci-app-xlnetacc luci-app-zerotier ca-certificates ddns-scripts_aliyun ddns-scripts_dnspod \
|
||||
luci-app-airplay2 luci-app-music-remote-center luci-app-qbittorrent luci-app-amule luci-app-openvpn-server luci-app-unblockmusic \
|
||||
ath10k-firmware-qca988x ath10k-firmware-qca9888 ath10k-firmware-qca9984 brcmfmac-firmware-43602a1-pcie \
|
||||
htop lm-sensors autocore-x86 automount autosamba luci-app-ipsec-vpnd luci-proto-bonding luci-app-xlnetacc luci-app-unblockmusic luci-app-zerotier \
|
||||
ath10k-firmware-qca988x ath10k-firmware-qca9888 ath10k-firmware-qca9984 brcmfmac-firmware-43602a1-pcie ca-certificates ddns-scripts_aliyun ddns-scripts_dnspod \
|
||||
kmod-sound-hda-core kmod-sound-hda-codec-realtek kmod-sound-hda-codec-via kmod-sound-via82xx kmod-sound-hda-intel kmod-sound-hda-codec-hdmi kmod-sound-i8x0 kmod-usb-audio \
|
||||
kmod-usb-net kmod-usb-net-asix kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8150 kmod-usb-net-rtl8152 kmod-mlx4-core kmod-mlx5-core
|
||||
|
||||
|
||||
@ -151,6 +151,7 @@ CONFIG_DECOMPRESS_BZIP2=y
|
||||
CONFIG_DECOMPRESS_GZIP=y
|
||||
CONFIG_DEFAULT_IO_DELAY_TYPE=0
|
||||
# CONFIG_DELL_RBU is not set
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_DMA_DIRECT_OPS=y
|
||||
CONFIG_DMI=y
|
||||
CONFIG_DMIID=y
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
--- a/arch/x86/kernel/reboot.c
|
||||
+++ b/arch/x86/kernel/reboot.c
|
||||
@@ -470,6 +470,16 @@ static struct dmi_system_id __initdata r
|
||||
@@ -478,6 +478,16 @@ static struct dmi_system_id __initdata r
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user