@@ -0,0 +1,283 @@
|
||||
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064-v2.0.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064-v2.0.dtsi
|
||||
@@ -22,6 +22,15 @@
|
||||
reg = <0x41200000 0x300000>;
|
||||
no-map;
|
||||
};
|
||||
+
|
||||
+ ramoops@42100000 {
|
||||
+ compatible = "ramoops";
|
||||
+ reg = <0x42100000 0x40000>;
|
||||
+ record-size = <0x4000>;
|
||||
+ console-size = <0x4000>;
|
||||
+ ftrace-size = <0x4000>;
|
||||
+ pmsg-size = <0x4000>;
|
||||
+ };
|
||||
};
|
||||
};
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
|
||||
@@ -670,6 +670,20 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ nss-common {
|
||||
+ compatible = "qcom,nss-common";
|
||||
+ reg = <0x03000000 0x00001000>;
|
||||
+ reg-names = "nss_fpb_base";
|
||||
+ clocks = <&gcc NSS_CORE_CLK>, <&gcc NSSTCM_CLK>,
|
||||
+ <&rpmcc RPM_NSS_FABRIC_0_CLK>, <&rpmcc RPM_NSS_FABRIC_1_CLK>;
|
||||
+ clock-names = "nss_core_clk", "nss_tcm_clk",
|
||||
+ "nss-fab0-clk", "nss-fab1-clk";
|
||||
+ nss_core-supply = <&smb208_s1b>;
|
||||
+ nss_core_vdd_nominal = <1100000>;
|
||||
+ nss_core_vdd_high = <1150000>;
|
||||
+ nss_core_threshold_freq = <733000000>;
|
||||
+ };
|
||||
+
|
||||
sfpb_mutex: hwlock@1200600 {
|
||||
compatible = "qcom,sfpb-mutex";
|
||||
reg = <0x01200600 0x100>;
|
||||
@@ -856,6 +870,132 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ nss0: nss@40000000 {
|
||||
+ compatible = "qcom,nss";
|
||||
+ qcom,low-frequency = <733000000>; /* orig value 110000000 */
|
||||
+ qcom,mid-frequency = <733000000>; /* orig value 550000000 */
|
||||
+ qcom,max-frequency = <733000000>;
|
||||
+
|
||||
+ interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ reg = <0x36000000 0x1000 0x39000000 0x10000>;
|
||||
+ reg-names = "nphys", "vphys";
|
||||
+ clocks = <&gcc NSS_CORE_CLK>, <&gcc NSSTCM_CLK_SRC>,
|
||||
+ <&gcc NSSTCM_CLK>, <&rpmcc RPM_NSS_FABRIC_0_CLK>,
|
||||
+ <&rpmcc RPM_NSS_FABRIC_1_CLK>;
|
||||
+ clock-names = "nss-core-clk", "nss-tcm-src",
|
||||
+ "nss-tcm-clk", "nss-fab0-clk",
|
||||
+ "nss-fab1-clk";
|
||||
+ resets = <&gcc UBI32_CORE1_CLKRST_CLAMP_RESET>,
|
||||
+ <&gcc UBI32_CORE1_CLAMP_RESET>,
|
||||
+ <&gcc UBI32_CORE1_AHB_RESET>,
|
||||
+ <&gcc UBI32_CORE1_AXI_RESET>;
|
||||
+ reset-names = "clkrst-clamp", "clamp", "ahb", "axi";
|
||||
+
|
||||
+ qcom,id = <0>;
|
||||
+ qcom,num-irq = <2>;
|
||||
+ qcom,num-queue = <2>;
|
||||
+ qcom,load-addr = <0x40000000>;
|
||||
+ qcom,turbo-frequency;
|
||||
+
|
||||
+ qcom,bridge-enabled;
|
||||
+ qcom,gre-enabled;
|
||||
+ qcom,gre-redir-enabled;
|
||||
+ qcom,gre_tunnel_enabled;
|
||||
+ qcom,ipv4-enabled;
|
||||
+ qcom,ipv4-reasm-enabled;
|
||||
+ qcom,ipv6-enabled;
|
||||
+ qcom,ipv6-reasm-enabled;
|
||||
+ qcom,l2tpv2-enabled;
|
||||
+ qcom,map-t-enabled;
|
||||
+ qcom,pppoe-enabled;
|
||||
+ qcom,pptp-enabled;
|
||||
+ qcom,portid-enabled;
|
||||
+ qcom,shaping-enabled;
|
||||
+ qcom,tun6rd-enabled;
|
||||
+ qcom,tunipip6-enabled;
|
||||
+ qcom,vlan-enabled;
|
||||
+ qcom,wlan-dataplane-offload-enabled;
|
||||
+ qcom,wlanredirect-enabled;
|
||||
+ qcom,pxvlan-enabled;
|
||||
+ qcom,vxlan-enabled;
|
||||
+ qcom,match-enabled;
|
||||
+ qcom,mirror-enabled;
|
||||
+ qcom,rmnet-enabled;
|
||||
+ qcom,clmap-enabled;
|
||||
+ };
|
||||
+
|
||||
+ nss1: nss@40800000 {
|
||||
+ compatible = "qcom,nss";
|
||||
+ qcom,low-frequency = <733000000>; /* orig value 110000000 */
|
||||
+ qcom,mid-frequency = <733000000>; /* orig value 550000000 */
|
||||
+ qcom,max-frequency = <733000000>;
|
||||
+
|
||||
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
|
||||
+ <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
|
||||
+ reg = <0x36400000 0x1000 0x39010000 0x10000>;
|
||||
+ reg-names = "nphys", "vphys";
|
||||
+ resets = <&gcc UBI32_CORE2_CLKRST_CLAMP_RESET>,
|
||||
+ <&gcc UBI32_CORE2_CLAMP_RESET>,
|
||||
+ <&gcc UBI32_CORE2_AHB_RESET>,
|
||||
+ <&gcc UBI32_CORE2_AXI_RESET>;
|
||||
+ reset-names = "clkrst-clamp", "clamp", "ahb", "axi";
|
||||
+
|
||||
+ qcom,id = <1>;
|
||||
+ qcom,num-irq = <2>;
|
||||
+ qcom,load-addr = <0x40800000>;
|
||||
+ qcom,num-queue = <2>;
|
||||
+ qcom,turbo-frequency;
|
||||
+
|
||||
+ qcom,capwap-enabled;
|
||||
+ qcom,crypto-enabled;
|
||||
+ qcom,dtls-enabled;
|
||||
+ qcom,ipsec-enabled;
|
||||
+ };
|
||||
+
|
||||
+ crypto1: crypto@38000000 {
|
||||
+ compatible = "qcom,nss-crypto";
|
||||
+ reg = <0x38000000 0x20000>, <0x38004000 0x22000>;
|
||||
+ reg-names = "crypto_pbase", "bam_base";
|
||||
+ clocks = <&gcc CE5_CORE_CLK>, <&gcc CE5_A_CLK>, <&gcc CE5_H_CLK>;
|
||||
+ clock-names = "ce5_core", "ce5_aclk", "ce5_hclk";
|
||||
+ resets = <&gcc CRYPTO_ENG1_RESET>, <&gcc CRYPTO_AHB_RESET>;
|
||||
+ reset-names = "rst_eng", "rst_ahb";
|
||||
+ qcom,id = <0>;
|
||||
+ qcom,ee = <0>;
|
||||
+ };
|
||||
+
|
||||
+ crypto2: crypto@38400000 {
|
||||
+ compatible = "qcom,nss-crypto";
|
||||
+ reg = <0x38400000 0x20000>, <0x38404000 0x22000>;
|
||||
+ reg-names = "crypto_pbase", "bam_base";
|
||||
+ resets = <&gcc CRYPTO_ENG2_RESET>;
|
||||
+ reset-names = "rst_eng";
|
||||
+ qcom,id = <1>;
|
||||
+ qcom,ee = <0>;
|
||||
+ };
|
||||
+
|
||||
+ crypto3: crypto@38800000 {
|
||||
+ compatible = "qcom,nss-crypto";
|
||||
+ reg = <0x38800000 0x20000>, <0x38804000 0x22000>;
|
||||
+ reg-names = "crypto_pbase", "bam_base";
|
||||
+ resets = <&gcc CRYPTO_ENG3_RESET>;
|
||||
+ reset-names = "rst_eng";
|
||||
+ qcom,id = <2>;
|
||||
+ qcom,ee = <0>;
|
||||
+ };
|
||||
+
|
||||
+ crypto4: crypto@38c00000 {
|
||||
+ compatible = "qcom,nss-crypto";
|
||||
+ reg = <0x38c00000 0x20000>, <0x38c04000 0x22000>;
|
||||
+ reg-names = "crypto_pbase", "bam_base";
|
||||
+ resets = <&gcc CRYPTO_ENG4_RESET>;
|
||||
+ reset-names = "rst_eng";
|
||||
+ qcom,id = <3>;
|
||||
+ qcom,ee = <0>;
|
||||
+ };
|
||||
+
|
||||
+
|
||||
sdcc3bam: dma-controller@12182000 {
|
||||
compatible = "qcom,bam-v1.3.0";
|
||||
reg = <0x12182000 0x8000>;
|
||||
@@ -1462,6 +1602,12 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
+ nss-gmac-common {
|
||||
+ compatible = "qcom,nss-gmac-common";
|
||||
+ reg = <0x03000000 0x0000FFFF 0x1bb00000 0x0000FFFF 0x00900000 0x00004000>;
|
||||
+ reg-names = "nss_reg_base", "qsgmii_reg_base", "clk_ctl_base";
|
||||
+ };
|
||||
+
|
||||
gmac0: ethernet@37000000 {
|
||||
device_type = "network";
|
||||
compatible = "qcom,ipq806x-gmac", "snps,dwmac";
|
||||
@@ -1559,3 +1705,27 @@
|
||||
};
|
||||
};
|
||||
};
|
||||
+
|
||||
+ &gmac1 {
|
||||
+ compatible = "qcom,nss-gmac";
|
||||
+ qcom,id = <0>;
|
||||
+ qcom,pcs-chanid = <0>;
|
||||
+ qcom,phy_mii_type = <0>;
|
||||
+ qcom,emulation = <0>;
|
||||
+ qcom,forced-speed = <1000>;
|
||||
+ qcom,forced-duplex = <1>;
|
||||
+ qcom,socver = <0>;
|
||||
+ mdiobus = <&mdio0>;
|
||||
+ };
|
||||
+
|
||||
+ &gmac2 {
|
||||
+ compatible = "qcom,nss-gmac";
|
||||
+ qcom,id = <1>;
|
||||
+ qcom,pcs-chanid = <1>;
|
||||
+ qcom,phy_mii_type = <1>;
|
||||
+ qcom,emulation = <0>;
|
||||
+ qcom,forced-speed = <1000>;
|
||||
+ qcom,forced-duplex = <1>;
|
||||
+ qcom,socver = <0>;
|
||||
+ mdiobus = <&mdio0>;
|
||||
+ };
|
||||
--- a/arch/arm/boot/dts/qcom/qcom-ipq8065-nighthawk.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8065-nighthawk.dtsi
|
||||
@@ -360,13 +360,23 @@
|
||||
&gmac1 {
|
||||
status = "okay";
|
||||
|
||||
+ compatible = "qcom,nss-gmac";
|
||||
+ reg = <0x37200000 0x200000>;
|
||||
+ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy-mode = "rgmii";
|
||||
qcom,id = <1>;
|
||||
+ qcom,pcs-chanid = <0>;
|
||||
qcom,phy_mdio_addr = <4>;
|
||||
qcom,poll_required = <0>;
|
||||
qcom,rgmii_delay = <1>;
|
||||
+ qcom,phy-mdio-addr = <4>;
|
||||
+ qcom,poll-required = <0>;
|
||||
+ qcom,rgmii-delay = <1>;
|
||||
qcom,phy_mii_type = <0>;
|
||||
qcom,emulation = <0>;
|
||||
+ qcom,forced-speed = <1000>;
|
||||
+ qcom,forced-duplex = <1>;
|
||||
+ qcom,socver = <0>;
|
||||
qcom,irq = <255>;
|
||||
mdiobus = <&mdio0>;
|
||||
|
||||
@@ -385,13 +395,23 @@
|
||||
&gmac2 {
|
||||
status = "okay";
|
||||
|
||||
+ compatible = "qcom,nss-gmac";
|
||||
+ reg = <0x37400000 0x200000>;
|
||||
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
|
||||
phy-mode = "sgmii";
|
||||
qcom,id = <2>;
|
||||
+ qcom,pcs-chanid = <1>;
|
||||
qcom,phy_mdio_addr = <0>; /* none */
|
||||
qcom,poll_required = <0>; /* no polling */
|
||||
qcom,rgmii_delay = <0>;
|
||||
+ qcom,phy-mdio-addr = <0>;
|
||||
+ qcom,poll-required = <0>;
|
||||
+ qcom,rgmii-delay = <0>;
|
||||
qcom,phy_mii_type = <1>;
|
||||
qcom,emulation = <0>;
|
||||
+ qcom,forced-speed = <1000>;
|
||||
+ qcom,forced-duplex = <1>;
|
||||
+ qcom,socver = <0>;
|
||||
qcom,irq = <258>;
|
||||
mdiobus = <&mdio0>;
|
||||
|
||||
--- a/arch/arm/boot/dts/qcom/qcom-ipq8065.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8065.dtsi
|
||||
@@ -95,3 +95,15 @@
|
||||
opp-level = <2>;
|
||||
};
|
||||
};
|
||||
+
|
||||
+ &nss0 {
|
||||
+ qcom,low-frequency = <110000000>;
|
||||
+ qcom,mid-frequency = <600000000>;
|
||||
+ qcom,max-frequency = <800000000>;
|
||||
+ };
|
||||
+
|
||||
+ &nss1 {
|
||||
+ qcom,low-frequency = <110000000>;
|
||||
+ qcom,mid-frequency = <600000000>;
|
||||
+ qcom,max-frequency = <800000000>;
|
||||
+ };
|
||||
@@ -0,0 +1,643 @@
|
||||
--- /dev/null
|
||||
+++ b/include/net/netfilter/nf_conntrack_dscpremark_ext.h
|
||||
@@ -0,0 +1,98 @@
|
||||
+/*
|
||||
+ **************************************************************************
|
||||
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. 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.
|
||||
+ **************************************************************************
|
||||
+ */
|
||||
+
|
||||
+/* DSCP remark conntrack extension APIs. */
|
||||
+
|
||||
+#ifndef _NF_CONNTRACK_DSCPREMARK_H
|
||||
+#define _NF_CONNTRACK_DSCPREMARK_H
|
||||
+#include <net/netfilter/nf_conntrack.h>
|
||||
+#include <net/netfilter/nf_conntrack_extend.h>
|
||||
+
|
||||
+/* Rule flags */
|
||||
+#define NF_CT_DSCPREMARK_EXT_DSCP_RULE_VALID 0x1
|
||||
+
|
||||
+/* Rule validity */
|
||||
+#define NF_CT_DSCPREMARK_EXT_RULE_VALID 0x1
|
||||
+#define NF_CT_DSCPREMARK_EXT_RULE_NOT_VALID 0x0
|
||||
+
|
||||
+/* Which QoS features are set flags */
|
||||
+#define NF_CT_DSCPREMARK_EXT_PRIO 0x1
|
||||
+#define NF_CT_DSCPREMARK_EXT_DSCP 0x2
|
||||
+#define NF_CT_DSCPREMARK_EXT_IGS_QOS 0x4
|
||||
+#define NF_CT_DSCPREMARK_EXT_MARK 0x8
|
||||
+#define NF_CT_DSCPREMARK_EXT_SAWF 0x10
|
||||
+
|
||||
+/*
|
||||
+ * DSCP remark conntrack extension structure.
|
||||
+ */
|
||||
+struct nf_ct_dscpremark_ext {
|
||||
+ __u32 flow_priority; /* Original direction packet priority */
|
||||
+ __u32 reply_priority; /* Reply direction packet priority */
|
||||
+ __u32 flow_mark; /* Original direction packet mark */
|
||||
+ __u32 reply_mark; /* Reply direction packet mark */
|
||||
+ __u32 flow_sawf_meta; /* Original direction SAWF meta info */
|
||||
+ __u32 return_sawf_meta; /* Reply direction SAWF meta info */
|
||||
+ __u16 igs_flow_qos_tag; /* Original direction ingress packet priority */
|
||||
+ __u16 igs_reply_qos_tag; /* Reply direction ingress packet priority */
|
||||
+ __u8 flow_dscp; /* IP DSCP value for original direction */
|
||||
+ __u8 reply_dscp; /* IP DSCP value for reply direction */
|
||||
+ __u16 rule_flags; /* Rule Validity flags */
|
||||
+ __u16 flow_set_flags; /* Original direction set flags */
|
||||
+ __u16 return_set_flags; /* Reply direction set flags */
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * nf_ct_dscpremark_ext_find()
|
||||
+ * Finds the extension data of the conntrack entry if it exists.
|
||||
+ */
|
||||
+static inline struct nf_ct_dscpremark_ext *
|
||||
+nf_ct_dscpremark_ext_find(const struct nf_conn *ct)
|
||||
+{
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ return nf_ct_ext_find(ct, NF_CT_EXT_DSCPREMARK);
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * nf_ct_dscpremark_ext_add()
|
||||
+ * Adds the extension data to the conntrack entry.
|
||||
+ */
|
||||
+static inline
|
||||
+struct nf_ct_dscpremark_ext *nf_ct_dscpremark_ext_add(struct nf_conn *ct,
|
||||
+ gfp_t gfp)
|
||||
+{
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ struct nf_ct_dscpremark_ext *ncde;
|
||||
+
|
||||
+ ncde = nf_ct_ext_add(ct, NF_CT_EXT_DSCPREMARK, gfp);
|
||||
+ if (!ncde)
|
||||
+ return NULL;
|
||||
+
|
||||
+ return ncde;
|
||||
+#else
|
||||
+ return NULL;
|
||||
+#endif
|
||||
+};
|
||||
+
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+extern int nf_conntrack_dscpremark_ext_set_dscp_rule_valid(struct nf_conn *ct);
|
||||
+extern int nf_conntrack_dscpremark_ext_get_dscp_rule_validity(struct nf_conn *ct);
|
||||
+#endif /* CONFIG_NF_CONNTRACK_DSCPREMARK_EXT */
|
||||
+
|
||||
+#endif /* _NF_CONNTRACK_DSCPREMARK_H */
|
||||
--- /dev/null
|
||||
+++ b/net/netfilter/nf_conntrack_dscpremark_ext.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/*
|
||||
+ **************************************************************************
|
||||
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
+ * Copyright (c) 2023, Qualcomm Innovation Center, Inc. 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.
|
||||
+ **************************************************************************
|
||||
+ */
|
||||
+
|
||||
+/* DSCP remark handling conntrack extension registration. */
|
||||
+
|
||||
+#include <linux/netfilter.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include <linux/export.h>
|
||||
+
|
||||
+#include <net/netfilter/nf_conntrack.h>
|
||||
+#include <net/netfilter/nf_conntrack_extend.h>
|
||||
+#include <net/netfilter/nf_conntrack_dscpremark_ext.h>
|
||||
+
|
||||
+/* nf_conntrack_dscpremark_ext_set_dscp_rule_valid()
|
||||
+ * Set DSCP rule validity flag in the extension
|
||||
+ */
|
||||
+int nf_conntrack_dscpremark_ext_set_dscp_rule_valid(struct nf_conn *ct)
|
||||
+{
|
||||
+ struct nf_ct_dscpremark_ext *ncde;
|
||||
+
|
||||
+ ncde = nf_ct_dscpremark_ext_find(ct);
|
||||
+ if (!ncde)
|
||||
+ return -1;
|
||||
+
|
||||
+ ncde->rule_flags = NF_CT_DSCPREMARK_EXT_DSCP_RULE_VALID;
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nf_conntrack_dscpremark_ext_set_dscp_rule_valid);
|
||||
+
|
||||
+/* nf_conntrack_dscpremark_ext_get_dscp_rule_validity()
|
||||
+ * Check if the DSCP rule flag is valid from the extension
|
||||
+ */
|
||||
+int nf_conntrack_dscpremark_ext_get_dscp_rule_validity(struct nf_conn *ct)
|
||||
+{
|
||||
+ struct nf_ct_dscpremark_ext *ncde;
|
||||
+
|
||||
+ ncde = nf_ct_dscpremark_ext_find(ct);
|
||||
+ if (!ncde)
|
||||
+ return NF_CT_DSCPREMARK_EXT_RULE_NOT_VALID;
|
||||
+
|
||||
+ if (ncde->rule_flags & NF_CT_DSCPREMARK_EXT_DSCP_RULE_VALID)
|
||||
+ return NF_CT_DSCPREMARK_EXT_RULE_VALID;
|
||||
+
|
||||
+ return NF_CT_DSCPREMARK_EXT_RULE_NOT_VALID;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nf_conntrack_dscpremark_ext_get_dscp_rule_validity);
|
||||
--- /dev/null
|
||||
+++ b/include/soc/qcom/socinfo.h
|
||||
@@ -0,0 +1,435 @@
|
||||
+/* Copyright (c) 2009-2014, 2016, 2020, The Linux Foundation. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 and
|
||||
+ * only version 2 as published by the Free Software Foundation.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef _ARCH_ARM_MACH_MSM_SOCINFO_H_
|
||||
+#define _ARCH_ARM_MACH_MSM_SOCINFO_H_
|
||||
+
|
||||
+#include <linux/of.h>
|
||||
+
|
||||
+#define CPU_IPQ4018 272
|
||||
+#define CPU_IPQ4019 273
|
||||
+#define CPU_IPQ4028 287
|
||||
+#define CPU_IPQ4029 288
|
||||
+
|
||||
+#define CPU_IPQ8062 201
|
||||
+#define CPU_IPQ8064 202
|
||||
+#define CPU_IPQ8066 203
|
||||
+#define CPU_IPQ8065 280
|
||||
+#define CPU_IPQ8068 204
|
||||
+#define CPU_IPQ8069 281
|
||||
+
|
||||
+#define CPU_IPQ8074 323
|
||||
+#define CPU_IPQ8072 342
|
||||
+#define CPU_IPQ8076 343
|
||||
+#define CPU_IPQ8078 344
|
||||
+#define CPU_IPQ8070 375
|
||||
+#define CPU_IPQ8071 376
|
||||
+
|
||||
+#define CPU_IPQ8072A 389
|
||||
+#define CPU_IPQ8074A 390
|
||||
+#define CPU_IPQ8076A 391
|
||||
+#define CPU_IPQ8078A 392
|
||||
+#define CPU_IPQ8070A 395
|
||||
+#define CPU_IPQ8071A 396
|
||||
+
|
||||
+#define CPU_IPQ8172 397
|
||||
+#define CPU_IPQ8173 398
|
||||
+#define CPU_IPQ8174 399
|
||||
+
|
||||
+#define CPU_IPQ6018 402
|
||||
+#define CPU_IPQ6028 403
|
||||
+#define CPU_IPQ6000 421
|
||||
+#define CPU_IPQ6010 422
|
||||
+#define CPU_IPQ6005 453
|
||||
+
|
||||
+/* TBD the CHIP IDs */
|
||||
+#define CPU_IPQ5000 425
|
||||
+#define CPU_IPQ5010 426
|
||||
+#define CPU_IPQ5018 427
|
||||
+
|
||||
+static inline const int* read_ipq_soc_version_major(void)
|
||||
+{
|
||||
+ const int *prop;
|
||||
+ prop = of_get_property(of_find_node_by_path("/"), "soc_version_major",
|
||||
+ NULL);
|
||||
+
|
||||
+ return prop;
|
||||
+}
|
||||
+
|
||||
+static inline int read_ipq_cpu_type(void)
|
||||
+{
|
||||
+ const int *prop;
|
||||
+ prop = of_get_property(of_find_node_by_path("/"), "cpu_type", NULL);
|
||||
+ /*
|
||||
+ * Return Default CPU type if "cpu_type" property is not found in DTSI
|
||||
+ */
|
||||
+ if (!prop)
|
||||
+ return CPU_IPQ8064;
|
||||
+ return *prop;
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq4018(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ4018;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq4019(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ4019;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq4028(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ4028;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq4029(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ4029;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq40xx(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return cpu_is_ipq4018() || cpu_is_ipq4019() ||
|
||||
+ cpu_is_ipq4028() || cpu_is_ipq4029();
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8062(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8062;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8064(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8064;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8066(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8066;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8068(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8068;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8065(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8065;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8069(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8069;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+static inline int cpu_is_ipq806x(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return cpu_is_ipq8062() || cpu_is_ipq8064() ||
|
||||
+ cpu_is_ipq8066() || cpu_is_ipq8068() ||
|
||||
+ cpu_is_ipq8065() || cpu_is_ipq8069();
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8070(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8070;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8071(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8071;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8072(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8072;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8074(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8074;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8076(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8076;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8078(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8078;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8072a(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8072A;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8074a(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8074A;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8076a(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8076A;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8078a(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8078A;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8070a(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8070A;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8071a(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8071A;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8172(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8172;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8173(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8173;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq8174(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ8174;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq6018(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ6018;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq6028(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ6028;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq6000(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ6000;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq6010(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ6010;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq6005(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ6005;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq5000(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ5000;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq5010(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ5010;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq5018(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return read_ipq_cpu_type() == CPU_IPQ5018;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq807x(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return cpu_is_ipq8072() || cpu_is_ipq8074() ||
|
||||
+ cpu_is_ipq8076() || cpu_is_ipq8078() ||
|
||||
+ cpu_is_ipq8070() || cpu_is_ipq8071() ||
|
||||
+ cpu_is_ipq8072a() || cpu_is_ipq8074a() ||
|
||||
+ cpu_is_ipq8076a() || cpu_is_ipq8078a() ||
|
||||
+ cpu_is_ipq8070a() || cpu_is_ipq8071a() ||
|
||||
+ cpu_is_ipq8172() || cpu_is_ipq8173() ||
|
||||
+ cpu_is_ipq8174();
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq60xx(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return cpu_is_ipq6018() || cpu_is_ipq6028() ||
|
||||
+ cpu_is_ipq6000() || cpu_is_ipq6010() ||
|
||||
+ cpu_is_ipq6005();
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static inline int cpu_is_ipq50xx(void)
|
||||
+{
|
||||
+#ifdef CONFIG_ARCH_QCOM
|
||||
+ return cpu_is_ipq5000() || cpu_is_ipq5010() ||
|
||||
+ cpu_is_ipq5018();
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+#endif /* _ARCH_ARM_MACH_MSM_SOCINFO_H_ */
|
||||
--- /dev/null
|
||||
+++ b/include/uapi/linux/tc_act/tc_nss_mirred.h
|
||||
@@ -0,0 +1,36 @@
|
||||
+#ifndef __LINUX_TC_NSS_MIRRED_H
|
||||
+#define __LINUX_TC_NSS_MIRRED_H
|
||||
+
|
||||
+#include <linux/pkt_cls.h>
|
||||
+
|
||||
+/*
|
||||
+ * Type of nss mirred action.
|
||||
+ */
|
||||
+#define TCA_ACT_MIRRED_NSS 17
|
||||
+
|
||||
+/*
|
||||
+ * Types of parameters for nss mirred action.
|
||||
+ */
|
||||
+enum {
|
||||
+ TC_NSS_MIRRED_UNSPEC,
|
||||
+ TC_NSS_MIRRED_TM,
|
||||
+ TC_NSS_MIRRED_PARMS,
|
||||
+ __TC_NSS_MIRRED_MAX
|
||||
+};
|
||||
+#define TC_NSS_MIRRED_MAX (__TC_NSS_MIRRED_MAX - 1)
|
||||
+
|
||||
+/*
|
||||
+ * tc_nss_mirred
|
||||
+ * tc command structure for nss mirred action.
|
||||
+ */
|
||||
+struct tc_nss_mirred {
|
||||
+ tc_gen; /* General tc structure. */
|
||||
+ __u32 from_ifindex; /* ifindex of the port from which traffic
|
||||
+ * will be redirected.
|
||||
+ */
|
||||
+ __u32 to_ifindex; /* ifindex of the port to which traffic
|
||||
+ * will be redirected.
|
||||
+ */
|
||||
+};
|
||||
+
|
||||
+#endif /* __LINUX_TC_NSS_MIRRED_H */
|
||||
@@ -0,0 +1,30 @@
|
||||
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
|
||||
@@ -1706,6 +1706,27 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ &rpm {
|
||||
+ smb208_regulators: regulators {
|
||||
+ compatible = "qcom,rpm-smb208-regulators";
|
||||
+
|
||||
+ smb208_s1a: s1a {
|
||||
+ regulator-min-microvolt = <1050000>;
|
||||
+ regulator-max-microvolt = <1150000>;
|
||||
+
|
||||
+ qcom,switch-mode-frequency = <1200000>;
|
||||
+ };
|
||||
+
|
||||
+ smb208_s1b: s1b {
|
||||
+ regulator-min-microvolt = <1050000>;
|
||||
+ regulator-max-microvolt = <1150000>;
|
||||
+
|
||||
+ qcom,switch-mode-frequency = <1200000>;
|
||||
+ };
|
||||
+
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
&gmac1 {
|
||||
compatible = "qcom,nss-gmac";
|
||||
qcom,id = <0>;
|
||||
@@ -0,0 +1,210 @@
|
||||
From c70758d96b22e4421a6afd824cb59e350c6a8040 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
Date: Tue, 2 Jun 2020 22:09:15 +0200
|
||||
Subject: [PATCH] Regulator: Add NSS VOLT
|
||||
|
||||
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
|
||||
---
|
||||
drivers/regulator/Kconfig | 7 +++++++
|
||||
drivers/regulator/Makefile | 1 +
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
--- a/drivers/regulator/Kconfig
|
||||
+++ b/drivers/regulator/Kconfig
|
||||
@@ -1663,4 +1663,11 @@ config REGULATOR_QCOM_LABIBB
|
||||
boost regulator and IBB can be used as a negative boost regulator
|
||||
for LCD display panel.
|
||||
|
||||
+config REGULATOR_NSS_VOLT
|
||||
+ bool "Qualcomm IPQ806X NSS Voltage regulator"
|
||||
+ depends on ARCH_QCOM || COMPILE_TEST
|
||||
+ help
|
||||
+ This driver provides support for the Qualcomm IPQ806X NSS Voltage
|
||||
+ regulator.
|
||||
+
|
||||
endif
|
||||
--- a/drivers/regulator/Makefile
|
||||
+++ b/drivers/regulator/Makefile
|
||||
@@ -195,5 +195,6 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x
|
||||
obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
|
||||
+obj-$(CONFIG_REGULATOR_NSS_VOLT) += nss-volt-ipq806x.o
|
||||
|
||||
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
|
||||
--- /dev/null
|
||||
+++ b/drivers/regulator/nss-volt-ipq806x.c
|
||||
@@ -0,0 +1,146 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2015-2016, 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.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/regulator/nss-volt-ipq806x.h>
|
||||
+
|
||||
+struct nss_data {
|
||||
+ struct regulator *nss_reg;
|
||||
+ u32 nss_core_vdd_nominal;
|
||||
+ u32 nss_core_vdd_high;
|
||||
+ u32 nss_core_threshold_freq;
|
||||
+};
|
||||
+
|
||||
+static struct nss_data *data;
|
||||
+
|
||||
+int nss_ramp_voltage(unsigned long rate, bool ramp_up)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int curr_uV, uV;
|
||||
+ struct regulator *reg;
|
||||
+
|
||||
+ if (!data) {
|
||||
+ pr_err("NSS core regulator not init.\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ reg = data->nss_reg;
|
||||
+
|
||||
+ if (!reg) {
|
||||
+ pr_err("NSS core regulator not found.\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (rate >= data->nss_core_threshold_freq)
|
||||
+ uV = data->nss_core_vdd_high;
|
||||
+ else
|
||||
+ uV = data->nss_core_vdd_nominal;
|
||||
+
|
||||
+ curr_uV = regulator_get_voltage(reg);
|
||||
+
|
||||
+ if (ramp_up) {
|
||||
+ if (uV <= curr_uV)
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ if (uV >= curr_uV)
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = regulator_set_voltage(reg, uV, data->nss_core_vdd_high);
|
||||
+ if (ret)
|
||||
+ pr_err("NSS volt scaling failed (%d)\n", uV);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id nss_ipq806x_match_table[] = {
|
||||
+ { .compatible = "qcom,nss-common" },
|
||||
+ {}
|
||||
+};
|
||||
+
|
||||
+static int nss_volt_ipq806x_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device_node *np = pdev->dev.of_node;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
+ if (!data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ data->nss_reg = devm_regulator_get(&pdev->dev, "nss_core");
|
||||
+ ret = PTR_ERR_OR_ZERO(data->nss_reg);
|
||||
+ if (ret) {
|
||||
+ if (ret == -EPROBE_DEFER)
|
||||
+ dev_dbg(&pdev->dev,
|
||||
+ "nss_core regulator not ready, retry\n");
|
||||
+ else
|
||||
+ dev_err(&pdev->dev, "no regulator for nss_core: %d\n",
|
||||
+ ret);
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ if (of_property_read_u32(np, "nss_core_vdd_nominal",
|
||||
+ &data->nss_core_vdd_nominal)) {
|
||||
+ pr_warn("NSS core vdd nominal not found. Using defaults...\n");
|
||||
+ data->nss_core_vdd_nominal = 1100000;
|
||||
+ }
|
||||
+
|
||||
+ if (of_property_read_u32(np, "nss_core_vdd_high",
|
||||
+ &data->nss_core_vdd_high)) {
|
||||
+ pr_warn("NSS core vdd high not found. Using defaults...\n");
|
||||
+ data->nss_core_vdd_high = 1150000;
|
||||
+ }
|
||||
+
|
||||
+ if (of_property_read_u32(np, "nss_core_threshold_freq",
|
||||
+ &data->nss_core_threshold_freq)) {
|
||||
+ pr_warn("NSS core thres freq not found. Using defaults...\n");
|
||||
+ data->nss_core_threshold_freq = 733000000;
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, data);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver nss_ipq806x_driver = {
|
||||
+ .probe = nss_volt_ipq806x_probe,
|
||||
+ .driver = {
|
||||
+ .name = "nss-volt-ipq806x",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = nss_ipq806x_match_table,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init nss_ipq806x_init(void)
|
||||
+{
|
||||
+ return platform_driver_register(&nss_ipq806x_driver);
|
||||
+}
|
||||
+late_initcall(nss_ipq806x_init);
|
||||
+
|
||||
+static void __exit nss_ipq806x_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&nss_ipq806x_driver);
|
||||
+}
|
||||
+module_exit(nss_ipq806x_exit);
|
||||
--- /dev/null
|
||||
+++ b/include/linux/regulator/nss-volt-ipq806x.h
|
||||
@@ -0,0 +1,24 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2015-2016, 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.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __QCOM_NSS_VOL_SCALING_H
|
||||
+#define __QCOM_NSS_VOL_SCALING_H
|
||||
+
|
||||
+#include <linux/regulator/consumer.h>
|
||||
+
|
||||
+int nss_ramp_voltage(unsigned long rate, bool ramp_up);
|
||||
+
|
||||
+#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
refs: linux-msm
|
||||
db30db7d342f
|
||||
42924e528bb6
|
||||
--- a/include/dt-bindings/clock/qcom,gcc-ipq806x.h
|
||||
+++ b/include/dt-bindings/clock/qcom,gcc-ipq806x.h
|
||||
@@ -283,6 +283,7 @@
|
||||
#define EBI2_AON_CLK 281
|
||||
#define NSSTCM_CLK_SRC 282
|
||||
#define NSSTCM_CLK 283
|
||||
+#define NSS_CORE_CLK 284 /* Virtual */
|
||||
#define CE5_A_CLK_SRC 285
|
||||
#define CE5_H_CLK_SRC 286
|
||||
#define CE5_CORE_CLK_SRC 287
|
||||
--- a/drivers/clk/qcom/gcc-ipq806x.c
|
||||
+++ b/drivers/clk/qcom/gcc-ipq806x.c
|
||||
@@ -24,6 +24,10 @@
|
||||
#include "clk-branch.h"
|
||||
#include "clk-hfpll.h"
|
||||
#include "reset.h"
|
||||
+#include <linux/regulator/nss-volt-ipq806x.h>
|
||||
+
|
||||
+/* NSS safe parent index which will be used during NSS PLL rate change */
|
||||
+static int gcc_ipq806x_nss_safe_parent;
|
||||
|
||||
static const struct clk_parent_data gcc_pxo[] = {
|
||||
{ .fw_name = "pxo", .name = "pxo" },
|
||||
@@ -2825,7 +2829,8 @@ static struct clk_dyn_rcg ubi32_core1_sr
|
||||
.parent_data = gcc_pxo_pll8_pll14_pll18_pll0,
|
||||
.num_parents = ARRAY_SIZE(gcc_pxo_pll8_pll14_pll18_pll0),
|
||||
.ops = &clk_dyn_rcg_ops,
|
||||
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE |
|
||||
+ CLK_IGNORE_UNUSED,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -2878,7 +2883,8 @@ static struct clk_dyn_rcg ubi32_core2_sr
|
||||
.parent_data = gcc_pxo_pll8_pll14_pll18_pll0,
|
||||
.num_parents = ARRAY_SIZE(gcc_pxo_pll8_pll14_pll18_pll0),
|
||||
.ops = &clk_dyn_rcg_ops,
|
||||
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE |
|
||||
+ CLK_IGNORE_UNUSED,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -3063,6 +3069,145 @@ static struct clk_branch ce5_h_clk = {
|
||||
},
|
||||
};
|
||||
|
||||
+static int nss_core_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * When ramping up voltage, it needs to be done first. This ensures that
|
||||
+ * the volt required will be available when you step up the frequency.
|
||||
+ */
|
||||
+ ret = nss_ramp_voltage(rate, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = clk_dyn_rcg_ops.set_rate(&ubi32_core1_src_clk.clkr.hw, rate,
|
||||
+ parent_rate);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = clk_dyn_rcg_ops.set_rate(&ubi32_core2_src_clk.clkr.hw, rate,
|
||||
+ parent_rate);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /*
|
||||
+ * When ramping down voltage, it needs to be set first. This ensures
|
||||
+ * that the volt required will be available until you step down the
|
||||
+ * frequency.
|
||||
+ */
|
||||
+ ret = nss_ramp_voltage(rate, false);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+nss_core_clk_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long parent_rate, u8 index)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * When ramping up voltage needs to be done first. This ensures that
|
||||
+ * the voltage required will be available when you step up the
|
||||
+ * frequency.
|
||||
+ */
|
||||
+ ret = nss_ramp_voltage(rate, true);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = clk_dyn_rcg_ops.set_rate_and_parent(
|
||||
+ &ubi32_core1_src_clk.clkr.hw, rate, parent_rate, index);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = clk_dyn_rcg_ops.set_rate_and_parent(
|
||||
+ &ubi32_core2_src_clk.clkr.hw, rate, parent_rate, index);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /*
|
||||
+ * When ramping down voltage needs to be done last. This ensures that
|
||||
+ * the voltage required will be available when you step down the
|
||||
+ * frequency.
|
||||
+ */
|
||||
+ ret = nss_ramp_voltage(rate, false);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int nss_core_clk_determine_rate(struct clk_hw *hw,
|
||||
+ struct clk_rate_request *req)
|
||||
+{
|
||||
+ return clk_dyn_rcg_ops.determine_rate(&ubi32_core1_src_clk.clkr.hw,
|
||||
+ req);
|
||||
+}
|
||||
+
|
||||
+static unsigned long
|
||||
+nss_core_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
+{
|
||||
+ return clk_dyn_rcg_ops.recalc_rate(&ubi32_core1_src_clk.clkr.hw,
|
||||
+ parent_rate);
|
||||
+}
|
||||
+
|
||||
+static u8 nss_core_clk_get_parent(struct clk_hw *hw)
|
||||
+{
|
||||
+ return clk_dyn_rcg_ops.get_parent(&ubi32_core1_src_clk.clkr.hw);
|
||||
+}
|
||||
+
|
||||
+static int nss_core_clk_set_parent(struct clk_hw *hw, u8 i)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct clk_dyn_rcg *rcg;
|
||||
+ struct freq_tbl f = { 200000000, P_PLL0, 2, 1, 2 };
|
||||
+
|
||||
+ /* P_PLL0 is 800 Mhz which needs to be divided for 200 Mhz */
|
||||
+ if (i == gcc_ipq806x_nss_safe_parent) {
|
||||
+ rcg = to_clk_dyn_rcg(&ubi32_core1_src_clk.clkr.hw);
|
||||
+ clk_dyn_configure_bank(rcg, &f);
|
||||
+
|
||||
+ rcg = to_clk_dyn_rcg(&ubi32_core2_src_clk.clkr.hw);
|
||||
+ clk_dyn_configure_bank(rcg, &f);
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = clk_dyn_rcg_ops.set_parent(&ubi32_core1_src_clk.clkr.hw, i);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ return clk_dyn_rcg_ops.set_parent(&ubi32_core2_src_clk.clkr.hw, i);
|
||||
+}
|
||||
+
|
||||
+static struct clk_hw *nss_core_clk_get_safe_parent(struct clk_hw *hw)
|
||||
+{
|
||||
+ return clk_hw_get_parent_by_index(hw, gcc_ipq806x_nss_safe_parent);
|
||||
+}
|
||||
+
|
||||
+static const struct clk_ops clk_ops_nss_core = {
|
||||
+ .set_rate = nss_core_clk_set_rate,
|
||||
+ .set_rate_and_parent = nss_core_clk_set_rate_and_parent,
|
||||
+ .determine_rate = nss_core_clk_determine_rate,
|
||||
+ .recalc_rate = nss_core_clk_recalc_rate,
|
||||
+ .get_parent = nss_core_clk_get_parent,
|
||||
+ .set_parent = nss_core_clk_set_parent,
|
||||
+ .get_safe_parent = nss_core_clk_get_safe_parent,
|
||||
+};
|
||||
+
|
||||
+/* Virtual clock for nss core clocks */
|
||||
+static struct clk_regmap nss_core_clk = {
|
||||
+ .hw.init = &(struct clk_init_data){
|
||||
+ .name = "nss_core_clk",
|
||||
+ .ops = &clk_ops_nss_core,
|
||||
+ .parent_data = gcc_pxo_pll8_pll14_pll18_pll0,
|
||||
+ .num_parents = 5,
|
||||
+ .flags = CLK_SET_RATE_PARENT,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static struct clk_regmap *gcc_ipq806x_clks[] = {
|
||||
[PLL0] = &pll0.clkr,
|
||||
[PLL0_VOTE] = &pll0_vote,
|
||||
@@ -3182,6 +3327,7 @@ static struct clk_regmap *gcc_ipq806x_cl
|
||||
[UBI32_CORE2_CLK_SRC] = &ubi32_core2_src_clk.clkr,
|
||||
[NSSTCM_CLK_SRC] = &nss_tcm_src.clkr,
|
||||
[NSSTCM_CLK] = &nss_tcm_clk.clkr,
|
||||
+ [NSS_CORE_CLK] = &nss_core_clk,
|
||||
[PLL9] = &hfpll0.clkr,
|
||||
[PLL10] = &hfpll1.clkr,
|
||||
[PLL12] = &hfpll_l2.clkr,
|
||||
@@ -3402,6 +3548,12 @@ static int gcc_ipq806x_probe(struct plat
|
||||
if (!regmap)
|
||||
return -ENODEV;
|
||||
|
||||
+ gcc_ipq806x_nss_safe_parent = qcom_find_src_index(&nss_core_clk.hw,
|
||||
+ gcc_pxo_pll8_pll14_pll18_pll0_map,
|
||||
+ P_PLL0);
|
||||
+ if (gcc_ipq806x_nss_safe_parent < 0)
|
||||
+ return gcc_ipq806x_nss_safe_parent;
|
||||
+
|
||||
/* Setup PLL18 static bits */
|
||||
regmap_update_bits(regmap, 0x31a4, 0xffffffc0, 0x40000400);
|
||||
regmap_write(regmap, 0x31b0, 0x3080);
|
||||
--- a/drivers/clk/qcom/clk-rcg.c
|
||||
+++ b/drivers/clk/qcom/clk-rcg.c
|
||||
@@ -818,6 +818,11 @@ static int clk_dyn_rcg_set_rate_and_pare
|
||||
return __clk_dyn_rcg_set_rate(hw, rate);
|
||||
}
|
||||
|
||||
+void clk_dyn_configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
|
||||
+{
|
||||
+ configure_bank(rcg, f);
|
||||
+}
|
||||
+
|
||||
const struct clk_ops clk_rcg_ops = {
|
||||
.enable = clk_enable_regmap,
|
||||
.disable = clk_disable_regmap,
|
||||
--- a/drivers/clk/qcom/clk-rcg.h
|
||||
+++ b/drivers/clk/qcom/clk-rcg.h
|
||||
@@ -191,4 +191,7 @@ struct clk_rcg_dfs_data {
|
||||
extern int qcom_cc_register_rcg_dfs(struct regmap *regmap,
|
||||
const struct clk_rcg_dfs_data *rcgs,
|
||||
size_t len);
|
||||
+
|
||||
+extern void clk_dyn_configure_bank(struct clk_dyn_rcg *rcg,
|
||||
+ const struct freq_tbl *f);
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
From a4851511e1d8e61a14c6f2345354c059cb964e6a Mon Sep 17 00:00:00 2001
|
||||
From: regae <37059068+regae@users.noreply.github.com>
|
||||
Date: Sat, 15 Jun 2024 19:16:36 +0700
|
||||
Subject: [PATCH 10/13] OpenWrt: 136-clk-Add-safe-switch-hook.patch
|
||||
|
||||
Sometimes clocks can't accept their parent source turning off
|
||||
while the source is reprogrammed to a different rate. Most
|
||||
notably CPU clocks require a way to switch away from the current
|
||||
PLL they're running on, reprogram that PLL to a new rate, and
|
||||
then switch back to the PLL with the new rate once they're done.
|
||||
Add a hook that drivers can implement allowing them to return a
|
||||
'safe parent' that they can switch their parent to while the
|
||||
upstream source is reprogrammed to support this.
|
||||
|
||||
---
|
||||
drivers/clk/clk.c | 61 +++++++++++++++++++++++++++++++-----
|
||||
include/linux/clk-provider.h | 1 +
|
||||
2 files changed, 54 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk.c
|
||||
+++ b/drivers/clk/clk.c
|
||||
@@ -69,9 +69,12 @@ struct clk_core {
|
||||
struct clk_parent_map *parents;
|
||||
u8 num_parents;
|
||||
u8 new_parent_index;
|
||||
+ u8 safe_parent_index;
|
||||
unsigned long rate;
|
||||
unsigned long req_rate;
|
||||
+ unsigned long old_rate;
|
||||
unsigned long new_rate;
|
||||
+ struct clk_core *safe_parent;
|
||||
struct clk_core *new_parent;
|
||||
struct clk_core *new_child;
|
||||
unsigned long flags;
|
||||
@@ -2240,7 +2243,8 @@ out:
|
||||
static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
|
||||
struct clk_core *new_parent, u8 p_index)
|
||||
{
|
||||
- struct clk_core *child;
|
||||
+ struct clk_core *child, *parent;
|
||||
+ struct clk_hw *parent_hw;
|
||||
|
||||
core->new_rate = new_rate;
|
||||
core->new_parent = new_parent;
|
||||
@@ -2250,6 +2254,18 @@ static void clk_calc_subtree(struct clk_
|
||||
if (new_parent && new_parent != core->parent)
|
||||
new_parent->new_child = core;
|
||||
|
||||
+ if (core->ops->get_safe_parent) {
|
||||
+ parent_hw = core->ops->get_safe_parent(core->hw);
|
||||
+ if (parent_hw) {
|
||||
+ parent = parent_hw->core;
|
||||
+ p_index = clk_fetch_parent_index(core, parent);
|
||||
+ core->safe_parent_index = p_index;
|
||||
+ core->safe_parent = parent;
|
||||
+ }
|
||||
+ } else {
|
||||
+ core->safe_parent = NULL;
|
||||
+ }
|
||||
+
|
||||
hlist_for_each_entry(child, &core->children, child_node) {
|
||||
child->new_rate = clk_recalc(child, new_rate);
|
||||
clk_calc_subtree(child, child->new_rate, NULL, 0);
|
||||
@@ -2351,14 +2367,43 @@ static struct clk_core *clk_propagate_ra
|
||||
unsigned long event)
|
||||
{
|
||||
struct clk_core *child, *tmp_clk, *fail_clk = NULL;
|
||||
+ struct clk_core *old_parent;
|
||||
int ret = NOTIFY_DONE;
|
||||
|
||||
- if (core->rate == core->new_rate)
|
||||
+ if (core->rate == core->new_rate && event != POST_RATE_CHANGE)
|
||||
return NULL;
|
||||
|
||||
+ switch (event) {
|
||||
+ case PRE_RATE_CHANGE:
|
||||
+ if (core->safe_parent)
|
||||
+ core->ops->set_parent(core->hw, core->safe_parent_index);
|
||||
+ core->old_rate = core->rate;
|
||||
+ break;
|
||||
+ case POST_RATE_CHANGE:
|
||||
+ if (core->safe_parent) {
|
||||
+ old_parent = __clk_set_parent_before(core,
|
||||
+ core->new_parent);
|
||||
+ if (core->ops->set_rate_and_parent) {
|
||||
+ core->ops->set_rate_and_parent(core->hw,
|
||||
+ core->new_rate,
|
||||
+ core->new_parent ?
|
||||
+ core->new_parent->rate : 0,
|
||||
+ core->new_parent_index);
|
||||
+ } else if (core->ops->set_parent) {
|
||||
+ core->ops->set_parent(core->hw,
|
||||
+ core->new_parent_index);
|
||||
+ }
|
||||
+ __clk_set_parent_after(core, core->new_parent,
|
||||
+ old_parent);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (core->notifier_count) {
|
||||
- ret = __clk_notify(core, event, core->rate, core->new_rate);
|
||||
- if (ret & NOTIFY_STOP_MASK)
|
||||
+ if (event != POST_RATE_CHANGE || core->old_rate != core->rate)
|
||||
+ ret = __clk_notify(core, event, core->old_rate,
|
||||
+ core->new_rate);
|
||||
+ if (ret & NOTIFY_STOP_MASK && event != POST_RATE_CHANGE)
|
||||
fail_clk = core;
|
||||
}
|
||||
|
||||
@@ -2413,7 +2458,8 @@ static void clk_change_rate(struct clk_c
|
||||
clk_core_enable_lock(core);
|
||||
}
|
||||
|
||||
- if (core->new_parent && core->new_parent != core->parent) {
|
||||
+ if (core->new_parent && core->new_parent != core->parent &&
|
||||
+ !core->safe_parent) {
|
||||
old_parent = __clk_set_parent_before(core, core->new_parent);
|
||||
trace_clk_set_parent(core, core->new_parent);
|
||||
|
||||
@@ -2450,9 +2496,6 @@ static void clk_change_rate(struct clk_c
|
||||
if (core->flags & CLK_OPS_PARENT_ENABLE)
|
||||
clk_core_disable_unprepare(parent);
|
||||
|
||||
- if (core->notifier_count && old_rate != core->rate)
|
||||
- __clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
|
||||
-
|
||||
if (core->flags & CLK_RECALC_NEW_RATES)
|
||||
(void)clk_calc_new_rates(core, core->new_rate);
|
||||
|
||||
@@ -2547,6 +2590,8 @@ static int clk_core_set_rate_nolock(stru
|
||||
clk_change_rate(top);
|
||||
|
||||
core->req_rate = req_rate;
|
||||
+ clk_propagate_rate_change(top, POST_RATE_CHANGE);
|
||||
+
|
||||
err:
|
||||
clk_pm_runtime_put(core);
|
||||
|
||||
--- a/include/linux/clk-provider.h
|
||||
+++ b/include/linux/clk-provider.h
|
||||
@@ -250,6 +250,7 @@ struct clk_ops {
|
||||
struct clk_rate_request *req);
|
||||
int (*set_parent)(struct clk_hw *hw, u8 index);
|
||||
u8 (*get_parent)(struct clk_hw *hw);
|
||||
+ struct clk_hw *(*get_safe_parent)(struct clk_hw *hw);
|
||||
int (*set_rate)(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate);
|
||||
int (*set_rate_and_parent)(struct clk_hw *hw,
|
||||
@@ -0,0 +1,159 @@
|
||||
From 16c72f2199f57a4b2f0295b8d08881cc94ad7e0b Mon Sep 17 00:00:00 2001
|
||||
From: Kathiravan T <kathirav@codeaurora.org>
|
||||
Date: Thu, 7 Feb 2013 12:15:11 -0800
|
||||
Subject: [PATCH 274/281] Revert "ARM: dma-mapping: remove dmac_clean_range and
|
||||
dmac_inv_range"
|
||||
|
||||
This partially reverts 'commit 702b94bff3c505 ("ARM: dma-mapping:
|
||||
remove dmac_clean_range and dmac_inv_range")'
|
||||
|
||||
Some MSM drivers still use the dmac_clean and dmac_inv_range APIs.
|
||||
Bring back the defines and exports for v7 CPUs.
|
||||
|
||||
Change-Id: I69017d73da1065a5eeb9c87c899b6a51be5ebfe6
|
||||
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
|
||||
Signed-off-by: Abhimanyu Kapur <abhimany@codeaurora.org>
|
||||
[sramana: resolved minor merge conflicts]
|
||||
Signed-off-by: Srinivas Ramana <sramana@codeaurora.org>
|
||||
[akdwived: Made change for checkpatch error]
|
||||
Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org>
|
||||
Signed-off-by: Vijayanand Jitta <vjitta@codeaurora.org>
|
||||
[qqzhou@codeaurora.org: Made change for compile error]
|
||||
Signed-off-by: Qingqing Zhou <qqzhou@codeaurora.org>
|
||||
|
||||
(cherry picked from commit 432d2898642443b498747a8e8a42cb423bd726f1)
|
||||
Signed-off-by: Kathiravan T <kathirav@codeaurora.org>
|
||||
|
||||
Change-Id: If81758c05ae89333205b8021a73287920a8ee64d
|
||||
Signed-off-by: Pavithra R <quic_pavir@quicinc.com>
|
||||
---
|
||||
arch/arm/include/asm/cacheflush.h | 21 +++++++++++++++++++++
|
||||
arch/arm/include/asm/glue-cache.h | 2 ++
|
||||
arch/arm/mm/cache-v7.S | 6 ++++--
|
||||
arch/arm/mm/proc-macros.S | 4 +++-
|
||||
arch/arm/mm/proc-syms.c | 3 +++
|
||||
5 files changed, 33 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/arm/include/asm/cacheflush.h
|
||||
+++ b/arch/arm/include/asm/cacheflush.h
|
||||
@@ -91,6 +91,21 @@
|
||||
* DMA Cache Coherency
|
||||
* ===================
|
||||
*
|
||||
+ * dma_inv_range(start, end)
|
||||
+ *
|
||||
+ * Invalidate (discard) the specified virtual address range.
|
||||
+ * May not write back any entries. If 'start' or 'end'
|
||||
+ * are not cache line aligned, those lines must be written
|
||||
+ * back.
|
||||
+ * - start - virtual start address
|
||||
+ * - end - virtual end address
|
||||
+ *
|
||||
+ * dma_clean_range(start, end)
|
||||
+ *
|
||||
+ * Clean (write back) the specified virtual address range.
|
||||
+ * - start - virtual start address
|
||||
+ * - end - virtual end address
|
||||
+ *
|
||||
* dma_flush_range(start, end)
|
||||
*
|
||||
* Clean and invalidate the specified virtual address range.
|
||||
@@ -112,6 +127,8 @@ struct cpu_cache_fns {
|
||||
void (*dma_map_area)(const void *, size_t, int);
|
||||
void (*dma_unmap_area)(const void *, size_t, int);
|
||||
|
||||
+ void (*dma_inv_range)(const void *, const void *);
|
||||
+ void (*dma_clean_range)(const void *, const void *);
|
||||
void (*dma_flush_range)(const void *, const void *);
|
||||
} __no_randomize_layout;
|
||||
|
||||
@@ -137,6 +154,8 @@ extern struct cpu_cache_fns cpu_cache;
|
||||
* is visible to DMA, or data written by DMA to system memory is
|
||||
* visible to the CPU.
|
||||
*/
|
||||
+#define dmac_inv_range cpu_cache.dma_inv_range
|
||||
+#define dmac_clean_range cpu_cache.dma_clean_range
|
||||
#define dmac_flush_range cpu_cache.dma_flush_range
|
||||
|
||||
#else
|
||||
@@ -156,6 +175,8 @@ extern void __cpuc_flush_dcache_area(voi
|
||||
* is visible to DMA, or data written by DMA to system memory is
|
||||
* visible to the CPU.
|
||||
*/
|
||||
+extern void dmac_inv_range(const void *, const void *);
|
||||
+extern void dmac_clean_range(const void *, const void *);
|
||||
extern void dmac_flush_range(const void *, const void *);
|
||||
|
||||
#endif
|
||||
--- a/arch/arm/include/asm/glue-cache.h
|
||||
+++ b/arch/arm/include/asm/glue-cache.h
|
||||
@@ -156,6 +156,8 @@ static inline void nop_dma_unmap_area(co
|
||||
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
|
||||
|
||||
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
|
||||
+#define dmac_inv_range __glue(_CACHE, _dma_inv_range)
|
||||
+#define dmac_clean_range __glue(_CACHE, _dma_clean_range)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
--- a/arch/arm/mm/cache-v7.S
|
||||
+++ b/arch/arm/mm/cache-v7.S
|
||||
@@ -361,7 +361,7 @@ ENDPROC(v7_flush_kern_dcache_area)
|
||||
* - start - virtual start address of region
|
||||
* - end - virtual end address of region
|
||||
*/
|
||||
-v7_dma_inv_range:
|
||||
+ENTRY(v7_dma_inv_range)
|
||||
dcache_line_size r2, r3
|
||||
sub r3, r2, #1
|
||||
tst r0, r3
|
||||
@@ -391,7 +391,7 @@ ENDPROC(v7_dma_inv_range)
|
||||
* - start - virtual start address of region
|
||||
* - end - virtual end address of region
|
||||
*/
|
||||
-v7_dma_clean_range:
|
||||
+ENTRY(v7_dma_clean_range)
|
||||
dcache_line_size r2, r3
|
||||
sub r3, r2, #1
|
||||
bic r0, r0, r3
|
||||
@@ -477,6 +477,8 @@ ENDPROC(v7_dma_unmap_area)
|
||||
|
||||
globl_equ b15_dma_map_area, v7_dma_map_area
|
||||
globl_equ b15_dma_unmap_area, v7_dma_unmap_area
|
||||
+ globl_equ b15_dma_inv_range, v7_dma_inv_range
|
||||
+ globl_equ b15_dma_clean_range, v7_dma_clean_range
|
||||
globl_equ b15_dma_flush_range, v7_dma_flush_range
|
||||
|
||||
define_cache_functions b15
|
||||
--- a/arch/arm/mm/proc-macros.S
|
||||
+++ b/arch/arm/mm/proc-macros.S
|
||||
@@ -326,7 +326,7 @@ ENTRY(\name\()_processor_functions)
|
||||
ENTRY(\name\()_cache_fns)
|
||||
.long \name\()_flush_icache_all
|
||||
.long \name\()_flush_kern_cache_all
|
||||
- .long \name\()_flush_kern_cache_louis
|
||||
+ .long \name\()_flush_kern_cache_louis
|
||||
.long \name\()_flush_user_cache_all
|
||||
.long \name\()_flush_user_cache_range
|
||||
.long \name\()_coherent_kern_range
|
||||
@@ -334,6 +334,8 @@ ENTRY(\name\()_cache_fns)
|
||||
.long \name\()_flush_kern_dcache_area
|
||||
.long \name\()_dma_map_area
|
||||
.long \name\()_dma_unmap_area
|
||||
+ .long \name\()_dma_inv_range
|
||||
+ .long \name\()_dma_clean_range
|
||||
.long \name\()_dma_flush_range
|
||||
.size \name\()_cache_fns, . - \name\()_cache_fns
|
||||
.endm
|
||||
--- a/arch/arm/mm/proc-syms.c
|
||||
+++ b/arch/arm/mm/proc-syms.c
|
||||
@@ -27,6 +27,9 @@ EXPORT_SYMBOL(__cpuc_flush_user_all);
|
||||
EXPORT_SYMBOL(__cpuc_flush_user_range);
|
||||
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
|
||||
EXPORT_SYMBOL(__cpuc_flush_dcache_area);
|
||||
+EXPORT_SYMBOL(dmac_inv_range);
|
||||
+EXPORT_SYMBOL(dmac_clean_range);
|
||||
+EXPORT_SYMBOL(dmac_flush_range);
|
||||
#else
|
||||
EXPORT_SYMBOL(cpu_cache);
|
||||
#endif
|
||||
@@ -0,0 +1,379 @@
|
||||
From fe56e8cb75f113577dbf3edb717ea967f3723e22 Mon Sep 17 00:00:00 2001
|
||||
From: Suman Ghosh <quic_sumaghos@quicinc.com>
|
||||
Date: Sat, 4 Sep 2021 01:09:20 +0530
|
||||
Subject: [PATCH 278/281] arm/arm64: Add new APIs to perform dma cache
|
||||
maintenance operation without dsb.
|
||||
|
||||
Change-Id: I511657af343c8dc668ab7280362b3cdd57579360
|
||||
Signed-off-by: Suman Ghosh <quic_sumaghos@quicinc.com>
|
||||
Signed-off-by: Tushar Ganatra <quic_tganatra@quicinc.com>
|
||||
Signed-off-by: Pavithra R <quic_pavir@quicinc.com>
|
||||
Signed-off-by: Tushar Ganatra <quic_tganatra@quicinc.com>
|
||||
---
|
||||
arch/arm/include/asm/cacheflush.h | 11 ++++
|
||||
arch/arm/include/asm/glue-cache.h | 3 +
|
||||
arch/arm/mm/cache-v7.S | 98 +++++++++++++++++++++++++++--
|
||||
arch/arm/mm/proc-syms.c | 3 +
|
||||
arch/arm64/include/asm/assembler.h | 39 ++++++++++++
|
||||
arch/arm64/include/asm/cacheflush.h | 9 +++
|
||||
arch/arm64/mm/cache.S | 58 +++++++++++++++++
|
||||
arch/arm64/mm/flush.c | 24 +++++++
|
||||
8 files changed, 239 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/arm/include/asm/cacheflush.h
|
||||
+++ b/arch/arm/include/asm/cacheflush.h
|
||||
@@ -130,6 +130,10 @@ struct cpu_cache_fns {
|
||||
void (*dma_inv_range)(const void *, const void *);
|
||||
void (*dma_clean_range)(const void *, const void *);
|
||||
void (*dma_flush_range)(const void *, const void *);
|
||||
+
|
||||
+ void (*dma_inv_range_no_dsb)(const void *, const void *);
|
||||
+ void (*dma_clean_range_no_dsb)(const void *, const void *);
|
||||
+ void (*dma_flush_range_no_dsb)(const void *, const void *);
|
||||
} __no_randomize_layout;
|
||||
|
||||
/*
|
||||
@@ -158,6 +162,10 @@ extern struct cpu_cache_fns cpu_cache;
|
||||
#define dmac_clean_range cpu_cache.dma_clean_range
|
||||
#define dmac_flush_range cpu_cache.dma_flush_range
|
||||
|
||||
+#define dmac_inv_range_no_dsb cpu_cache.dma_inv_range_no_dsb
|
||||
+#define dmac_clean_range_no_dsb cpu_cache.dma_clean_range_no_dsb
|
||||
+#define dmac_flush_range_no_dsb cpu_cache.dma_flush_range_no_dsb
|
||||
+
|
||||
#else
|
||||
|
||||
extern void __cpuc_flush_icache_all(void);
|
||||
@@ -178,6 +186,9 @@ extern void __cpuc_flush_dcache_area(voi
|
||||
extern void dmac_inv_range(const void *, const void *);
|
||||
extern void dmac_clean_range(const void *, const void *);
|
||||
extern void dmac_flush_range(const void *, const void *);
|
||||
+extern void dmac_inv_range_no_dsb(const void *, const void *);
|
||||
+extern void dmac_clean_range_no_dsb(const void *, const void *);
|
||||
+extern void dmac_flush_range_no_dsb(const void *, const void *);
|
||||
|
||||
#endif
|
||||
|
||||
--- a/arch/arm/include/asm/glue-cache.h
|
||||
+++ b/arch/arm/include/asm/glue-cache.h
|
||||
@@ -156,8 +156,11 @@ static inline void nop_dma_unmap_area(co
|
||||
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
|
||||
|
||||
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
|
||||
+#define dmac_flush_range_no_dsb __glue(_CACHE,_dma_flush_range_no_dsb)
|
||||
#define dmac_inv_range __glue(_CACHE, _dma_inv_range)
|
||||
+#define dmac_inv_range_no_dsb __glue(_CACHE, _dma_inv_range_no_dsb)
|
||||
#define dmac_clean_range __glue(_CACHE, _dma_clean_range)
|
||||
+#define dmac_clean_range_no_dsb __glue(_CACHE, _dma_clean_range_no_dsb)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
--- a/arch/arm/mm/cache-v7.S
|
||||
+++ b/arch/arm/mm/cache-v7.S
|
||||
@@ -387,6 +387,42 @@ ENTRY(v7_dma_inv_range)
|
||||
ENDPROC(v7_dma_inv_range)
|
||||
|
||||
/*
|
||||
+ * v7_dma_inv_range_no_dsb(start,end)
|
||||
+ *
|
||||
+ * Invalidate the data cache within the specified region; we will
|
||||
+ * be performing a DMA operation in this region and we want to
|
||||
+ * purge old data in the cache. This API does not do
|
||||
+ * "data synchronization barrier". The caller is responsible to
|
||||
+ * do dsb after the transaction.
|
||||
+ *
|
||||
+ * - start - virtual start address of region
|
||||
+ * - end - virtual end address of region
|
||||
+ */
|
||||
+ENTRY(v7_dma_inv_range_no_dsb)
|
||||
+ dcache_line_size r2, r3
|
||||
+ sub r3, r2, #1
|
||||
+ tst r0, r3
|
||||
+ bic r0, r0, r3
|
||||
+#ifdef CONFIG_ARM_ERRATA_764369
|
||||
+ ALT_SMP(W(dsb))
|
||||
+ ALT_UP(W(nop))
|
||||
+#endif
|
||||
+ mcrne p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
||||
+ addne r0, r0, r2
|
||||
+
|
||||
+ tst r1, r3
|
||||
+ bic r1, r1, r3
|
||||
+ mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D / U line
|
||||
+ cmp r0, r1
|
||||
+1:
|
||||
+ mcrlo p15, 0, r0, c7, c6, 1 @ invalidate D / U line
|
||||
+ addlo r0, r0, r2
|
||||
+ cmplo r0, r1
|
||||
+ blo 1b
|
||||
+ ret lr
|
||||
+ENDPROC(v7_dma_inv_range_no_dsb)
|
||||
+
|
||||
+/*
|
||||
* v7_dma_clean_range(start,end)
|
||||
* - start - virtual start address of region
|
||||
* - end - virtual end address of region
|
||||
@@ -409,12 +445,16 @@ ENTRY(v7_dma_clean_range)
|
||||
ENDPROC(v7_dma_clean_range)
|
||||
|
||||
/*
|
||||
- * v7_dma_flush_range(start,end)
|
||||
+ * v7_dma_clean_range_no_dsb(start,end)
|
||||
+ *
|
||||
+ * This API does not do "data synchronization barrier".
|
||||
+ * The caller is responsible to do dsb after the transaction.
|
||||
+ *
|
||||
* - start - virtual start address of region
|
||||
* - end - virtual end address of region
|
||||
*/
|
||||
-ENTRY(v7_dma_flush_range)
|
||||
- dcache_line_size r2, r3
|
||||
+ENTRY(v7_dma_clean_range_no_dsb)
|
||||
+ dcache_line_size r2, r3
|
||||
sub r3, r2, #1
|
||||
bic r0, r0, r3
|
||||
#ifdef CONFIG_ARM_ERRATA_764369
|
||||
@@ -422,6 +462,27 @@ ENTRY(v7_dma_flush_range)
|
||||
ALT_UP(W(nop))
|
||||
#endif
|
||||
1:
|
||||
+ mcr p15, 0, r0, c7, c10, 1 @ clean D / U line
|
||||
+ add r0, r0, r2
|
||||
+ cmp r0, r1
|
||||
+ blo 1b
|
||||
+ ret lr
|
||||
+ENDPROC(v7_dma_clean_range_no_dsb)
|
||||
+
|
||||
+/*
|
||||
+ * v7_dma_flush_range(start,end)
|
||||
+ * - start - virtual start address of region
|
||||
+ * - end - virtual end address of region
|
||||
+ */
|
||||
+ENTRY(v7_dma_flush_range)
|
||||
+ dcache_line_size r2, r3
|
||||
+ sub r3, r2, #1
|
||||
+ bic r0, r0, r3
|
||||
+#ifdef CONFIG_ARM_ERRATA_764369
|
||||
+ ALT_SMP(W(dsb))
|
||||
+ ALT_UP(W(nop))
|
||||
+#endif
|
||||
+1:
|
||||
mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
||||
add r0, r0, r2
|
||||
cmp r0, r1
|
||||
@@ -431,10 +492,35 @@ ENTRY(v7_dma_flush_range)
|
||||
ENDPROC(v7_dma_flush_range)
|
||||
|
||||
/*
|
||||
+ * v7_dma_flush_range_no_dsb(start,end)
|
||||
+ *
|
||||
+ * This API does not do "data synchronization barrier".
|
||||
+ * The caller is responsible to do dsb after the transaction.
|
||||
+ *
|
||||
+ * - start - virtual start address of region
|
||||
+ * - end - virtual end address of region
|
||||
+ */
|
||||
+ENTRY(v7_dma_flush_range_no_dsb)
|
||||
+ dcache_line_size r2, r3
|
||||
+ sub r3, r2, #1
|
||||
+ bic r0, r0, r3
|
||||
+#ifdef CONFIG_ARM_ERRATA_764369
|
||||
+ ALT_SMP(W(dsb))
|
||||
+ ALT_UP(W(nop))
|
||||
+#endif
|
||||
+1:
|
||||
+ mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D / U line
|
||||
+ add r0, r0, r2
|
||||
+ cmp r0, r1
|
||||
+ blo 1b
|
||||
+ ret lr
|
||||
+ENDPROC(v7_dma_flush_range_no_dsb)
|
||||
+
|
||||
+/*
|
||||
* dma_map_area(start, size, dir)
|
||||
- * - start - kernel virtual start address
|
||||
- * - size - size of region
|
||||
- * - dir - DMA direction
|
||||
+ * - start - kernel virtual start address
|
||||
+ * - size - size of region
|
||||
+ * - dir - DMA direction
|
||||
*/
|
||||
ENTRY(v7_dma_map_area)
|
||||
add r1, r1, r0
|
||||
--- a/arch/arm/mm/proc-syms.c
|
||||
+++ b/arch/arm/mm/proc-syms.c
|
||||
@@ -28,8 +28,11 @@ EXPORT_SYMBOL(__cpuc_flush_user_range);
|
||||
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
|
||||
EXPORT_SYMBOL(__cpuc_flush_dcache_area);
|
||||
EXPORT_SYMBOL(dmac_inv_range);
|
||||
+EXPORT_SYMBOL(dmac_inv_range_no_dsb);
|
||||
EXPORT_SYMBOL(dmac_clean_range);
|
||||
+EXPORT_SYMBOL(dmac_clean_range_no_dsb);
|
||||
EXPORT_SYMBOL(dmac_flush_range);
|
||||
+EXPORT_SYMBOL(dmac_flush_range_no_dsb);
|
||||
#else
|
||||
EXPORT_SYMBOL(cpu_cache);
|
||||
#endif
|
||||
--- a/arch/arm64/include/asm/assembler.h
|
||||
+++ b/arch/arm64/include/asm/assembler.h
|
||||
@@ -428,6 +428,45 @@ alternative_endif
|
||||
|
||||
/*
|
||||
* Macro to perform a data cache maintenance for the interval
|
||||
+ * [kaddr, kaddr + size)
|
||||
+ * This macro does not do "data synchronization barrier". Caller should
|
||||
+ * do "dsb" after transaction.
|
||||
+ *
|
||||
+ * op: operation passed to dc instruction
|
||||
+ * kaddr: starting virtual address of the region
|
||||
+ * size: size of the region
|
||||
+ * Corrupts: kaddr, size, tmp1, tmp2
|
||||
+ */
|
||||
+ .macro dcache_by_line_op_no_dsb op, kaddr, size, tmp1, tmp2
|
||||
+ dcache_line_size \tmp1, \tmp2
|
||||
+ add \size, \kaddr, \size
|
||||
+ sub \tmp2, \tmp1, #1
|
||||
+ bic \kaddr, \kaddr, \tmp2
|
||||
+9998:
|
||||
+ .ifc \op, cvau
|
||||
+ __dcache_op_workaround_clean_cache \op, \kaddr
|
||||
+ .else
|
||||
+ .ifc \op, cvac
|
||||
+ __dcache_op_workaround_clean_cache \op, \kaddr
|
||||
+ .else
|
||||
+ .ifc \op, cvap
|
||||
+ sys 3, c7, c12, 1, \kaddr // dc cvap
|
||||
+ .else
|
||||
+ .ifc \op, cvadp
|
||||
+ sys 3, c7, c13, 1, \kaddr // dc cvadp
|
||||
+ .else
|
||||
+ dc \op, \kaddr
|
||||
+ .endif
|
||||
+ .endif
|
||||
+ .endif
|
||||
+ .endif
|
||||
+ add \kaddr, \kaddr, \tmp1
|
||||
+ cmp \kaddr, \size
|
||||
+ b.lo 9998b
|
||||
+ .endm
|
||||
+
|
||||
+/*
|
||||
+ * Macro to perform a data cache maintenance for the interval
|
||||
* [start, end)
|
||||
*
|
||||
* op: operation passed to dc instruction
|
||||
--- a/arch/arm64/include/asm/cacheflush.h
|
||||
+++ b/arch/arm64/include/asm/cacheflush.h
|
||||
@@ -79,6 +79,15 @@ extern void dcache_clean_pou(unsigned lo
|
||||
extern long caches_clean_inval_user_pou(unsigned long start, unsigned long end);
|
||||
extern void sync_icache_aliases(unsigned long start, unsigned long end);
|
||||
|
||||
+extern void dmac_inv_range(const void *start, const void *end);
|
||||
+extern void __dma_flush_area_no_dsb(const void *start, size_t size);
|
||||
+extern void __dma_inv_area_no_dsb(const void *start, size_t size);
|
||||
+extern void __dma_clean_area_no_dsb(const void *start, size_t size);
|
||||
+
|
||||
+extern void dmac_flush_range_no_dsb(const void *start, const void *end);
|
||||
+extern void dmac_inv_range_no_dsb(const void *start, const void *end);
|
||||
+extern void dmac_clean_range_no_dsb(const void *start, const void *end);
|
||||
+
|
||||
static inline void flush_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
caches_clean_inval_pou(start, end);
|
||||
--- a/arch/arm64/mm/cache.S
|
||||
+++ b/arch/arm64/mm/cache.S
|
||||
@@ -164,6 +164,64 @@ SYM_FUNC_END(__pi_dcache_inval_poc)
|
||||
SYM_FUNC_ALIAS(dcache_inval_poc, __pi_dcache_inval_poc)
|
||||
|
||||
/*
|
||||
+ * __dma_inv_area_no_dsb(start, size)
|
||||
+ *
|
||||
+ * This macro does not do "data synchronization barrier". Caller should
|
||||
+ * do "dsb" after transaction.
|
||||
+ *
|
||||
+ * start - virtual start address of region
|
||||
+ * size - size in question
|
||||
+ */
|
||||
+SYM_FUNC_START(__dma_inv_area_no_dsb)
|
||||
+ add x1, x1, x0
|
||||
+ dcache_line_size x2, x3
|
||||
+ sub x3, x2, #1
|
||||
+ tst x1, x3 // end cache line aligned?
|
||||
+ bic x1, x1, x3
|
||||
+ b.eq 1f
|
||||
+ dc civac, x1 // clean & invalidate D / U line
|
||||
+1: tst x0, x3 // start cache line aligned?
|
||||
+ bic x0, x0, x3
|
||||
+ b.eq 2f
|
||||
+ dc civac, x0 // clean & invalidate D / U line
|
||||
+ b 3f
|
||||
+2: dc ivac, x0 // invalidate D / U line
|
||||
+3: add x0, x0, x2
|
||||
+ cmp x0, x1
|
||||
+ b.lo 2b
|
||||
+ ret
|
||||
+SYM_FUNC_END(__dma_inv_area_no_dsb)
|
||||
+
|
||||
+/*
|
||||
+ * __dma_clean_area_no_dsb(start, size)
|
||||
+ *
|
||||
+ * his macro does not do "data synchronization barrier". Caller should
|
||||
+ * o "dsb" after transaction.
|
||||
+ *
|
||||
+ * start - virtual start address of region
|
||||
+ * size - size in question
|
||||
+ */
|
||||
+SYM_FUNC_START(__dma_clean_area_no_dsb)
|
||||
+ dcache_by_line_op_no_dsb cvac, x0, x1, x2, x3
|
||||
+ ret
|
||||
+SYM_FUNC_END(__dma_clean_area_no_dsb)
|
||||
+
|
||||
+/*
|
||||
+ * __dma_flush_area_no_dsb(start, size)
|
||||
+ *
|
||||
+ * clean & invalidate D / U line
|
||||
+ * his macro does not do "data synchronization barrier". Caller should
|
||||
+ * o "dsb" after transaction.
|
||||
+ *
|
||||
+ * start - virtual start address of region
|
||||
+ * size - size in question
|
||||
+ */
|
||||
+SYM_FUNC_START(__dma_flush_area_no_dsb)
|
||||
+ dcache_by_line_op_no_dsb civac, x0, x1, x2, x3
|
||||
+ ret
|
||||
+SYM_FUNC_END(__dma_flush_area_no_dsb)
|
||||
+
|
||||
+/*
|
||||
* dcache_clean_poc(start, end)
|
||||
*
|
||||
* Ensure that any D-cache lines for the interval [start, end)
|
||||
--- a/arch/arm64/mm/flush.c
|
||||
+++ b/arch/arm64/mm/flush.c
|
||||
@@ -100,3 +100,27 @@ void arch_invalidate_pmem(void *addr, si
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
|
||||
#endif
|
||||
+
|
||||
+void dmac_flush_range_no_dsb(const void *start, const void *end)
|
||||
+{
|
||||
+ __dma_flush_area_no_dsb(start, (void *)(end) - (void *)(start));
|
||||
+}
|
||||
+EXPORT_SYMBOL(dmac_flush_range_no_dsb);
|
||||
+
|
||||
+void dmac_inv_range(const void *start, const void *end)
|
||||
+{
|
||||
+ dcache_inval_poc((unsigned long)start, (unsigned long)(end));
|
||||
+}
|
||||
+EXPORT_SYMBOL(dmac_inv_range);
|
||||
+
|
||||
+void dmac_inv_range_no_dsb(const void *start, const void *end)
|
||||
+{
|
||||
+ __dma_inv_area_no_dsb(start, (void *)(end) - (void *)(start));
|
||||
+}
|
||||
+EXPORT_SYMBOL(dmac_inv_range_no_dsb);
|
||||
+
|
||||
+void dmac_clean_range_no_dsb(const void *start, const void *end)
|
||||
+{
|
||||
+ __dma_clean_area_no_dsb(start, (void *)(end) - (void *)(start));
|
||||
+}
|
||||
+EXPORT_SYMBOL(dmac_clean_range_no_dsb);
|
||||
@@ -0,0 +1,143 @@
|
||||
From 5f63a10caee09a5cec9a0da7f6b9cde39decf0c7 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
Date: Thu, 11 May 2023 11:54:05 -0700
|
||||
Subject: [PATCH 269/281] net: Add DSCP remarking feature for HW acceleration.
|
||||
|
||||
DSCP remarking is an advanced QoS feature of acceleration
|
||||
engine. With this feature it is possible to set the accelerated
|
||||
eggress packets' DSCP values with iptables command.
|
||||
|
||||
Change-Id: I7fa8d8a2a87b66b262d54e25f22e9eedd665c456
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
---
|
||||
include/net/netfilter/nf_conntrack_extend.h | 3 +++
|
||||
net/netfilter/Kconfig | 7 ++++++
|
||||
net/netfilter/Makefile | 1 +
|
||||
net/netfilter/nf_conntrack_core.c | 6 +++++
|
||||
net/netfilter/xt_DSCP.c | 27 ++++++++++++++++++++-
|
||||
5 files changed, 43 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/net/netfilter/nf_conntrack_extend.h
|
||||
+++ b/include/net/netfilter/nf_conntrack_extend.h
|
||||
@@ -31,6 +31,9 @@ enum nf_ct_ext_id {
|
||||
#if IS_ENABLED(CONFIG_NET_ACT_CT)
|
||||
NF_CT_EXT_ACT_CT,
|
||||
#endif
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ NF_CT_EXT_DSCPREMARK,
|
||||
+#endif
|
||||
NF_CT_EXT_NUM,
|
||||
};
|
||||
|
||||
--- a/net/netfilter/Kconfig
|
||||
+++ b/net/netfilter/Kconfig
|
||||
@@ -174,6 +174,13 @@ config NF_CONNTRACK_TIMEOUT
|
||||
|
||||
If unsure, say `N'.
|
||||
|
||||
+config NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ bool 'Connection tracking extension for dscp remark target'
|
||||
+ depends on NETFILTER_ADVANCED
|
||||
+ help
|
||||
+ This option enables support for connection tracking extension
|
||||
+ for dscp remark.
|
||||
+
|
||||
config NF_CONNTRACK_TIMESTAMP
|
||||
bool 'Connection tracking timestamping'
|
||||
depends on NETFILTER_ADVANCED
|
||||
--- a/net/netfilter/Makefile
|
||||
+++ b/net/netfilter/Makefile
|
||||
@@ -20,6 +20,7 @@ nf_conntrack-$(CONFIG_DEBUG_INFO_BTF_MOD
|
||||
else ifeq ($(CONFIG_NF_CONNTRACK),y)
|
||||
nf_conntrack-$(CONFIG_DEBUG_INFO_BTF) += nf_conntrack_bpf.o
|
||||
endif
|
||||
+nf_conntrack-$(CONFIG_NF_CONNTRACK_DSCPREMARK_EXT) += nf_conntrack_dscpremark_ext.o
|
||||
|
||||
obj-$(CONFIG_NETFILTER) = netfilter.o
|
||||
obj-$(CONFIG_NETFILTER_BPF_LINK) += nf_bpf_link.o
|
||||
--- a/net/netfilter/nf_conntrack_core.c
|
||||
+++ b/net/netfilter/nf_conntrack_core.c
|
||||
@@ -45,6 +45,9 @@
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/nf_conntrack_timestamp.h>
|
||||
#include <net/netfilter/nf_conntrack_timeout.h>
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+#include <net/netfilter/nf_conntrack_dscpremark_ext.h>
|
||||
+#endif
|
||||
#include <net/netfilter/nf_conntrack_labels.h>
|
||||
#include <net/netfilter/nf_conntrack_synproxy.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
@@ -1740,6 +1743,9 @@ init_conntrack(struct net *net, struct n
|
||||
nf_ct_acct_ext_add(ct, GFP_ATOMIC);
|
||||
nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
|
||||
nf_ct_labels_ext_add(ct);
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ nf_ct_dscpremark_ext_add(ct, GFP_ATOMIC);
|
||||
+#endif
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL;
|
||||
--- a/net/netfilter/xt_DSCP.c
|
||||
+++ b/net/netfilter/xt_DSCP.c
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter/xt_DSCP.h>
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+#include <net/netfilter/nf_conntrack_dscpremark_ext.h>
|
||||
+#endif
|
||||
|
||||
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification");
|
||||
@@ -31,6 +34,10 @@ dscp_tg(struct sk_buff *skb, const struc
|
||||
{
|
||||
const struct xt_DSCP_info *dinfo = par->targinfo;
|
||||
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ struct nf_conn *ct;
|
||||
+ enum ip_conntrack_info ctinfo;
|
||||
+#endif
|
||||
|
||||
if (dscp != dinfo->dscp) {
|
||||
if (skb_ensure_writable(skb, sizeof(struct iphdr)))
|
||||
@@ -39,6 +46,13 @@ dscp_tg(struct sk_buff *skb, const struc
|
||||
ipv4_change_dsfield(ip_hdr(skb), XT_DSCP_ECN_MASK,
|
||||
dinfo->dscp << XT_DSCP_SHIFT);
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ ct = nf_ct_get(skb, &ctinfo);
|
||||
+ if (!ct)
|
||||
+ return XT_CONTINUE;
|
||||
+
|
||||
+ nf_conntrack_dscpremark_ext_set_dscp_rule_valid(ct);
|
||||
+#endif
|
||||
}
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
@@ -48,13 +62,24 @@ dscp_tg6(struct sk_buff *skb, const stru
|
||||
{
|
||||
const struct xt_DSCP_info *dinfo = par->targinfo;
|
||||
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
|
||||
-
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ struct nf_conn *ct;
|
||||
+ enum ip_conntrack_info ctinfo;
|
||||
+#endif
|
||||
if (dscp != dinfo->dscp) {
|
||||
if (skb_ensure_writable(skb, sizeof(struct ipv6hdr)))
|
||||
return NF_DROP;
|
||||
|
||||
ipv6_change_dsfield(ipv6_hdr(skb), XT_DSCP_ECN_MASK,
|
||||
dinfo->dscp << XT_DSCP_SHIFT);
|
||||
+
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ ct = nf_ct_get(skb, &ctinfo);
|
||||
+ if (!ct)
|
||||
+ return XT_CONTINUE;
|
||||
+
|
||||
+ nf_conntrack_dscpremark_ext_set_dscp_rule_valid(ct);
|
||||
+#endif
|
||||
}
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
From 8daa619cff9acc2be5c0161019cd33e486171047 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Tue, 18 Apr 2017 15:48:01 -0700
|
||||
Subject: [PATCH 270/281] net: conntrack events, support multiple registrant
|
||||
|
||||
Change-Id: Iebfb254590fb594f5baf232f849d1b7ae45ef757
|
||||
Signed-off-by: Zhi Chen <zhichen@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/net/netfilter/nf_conntrack_ecache.h | 45 +++++++++++++-
|
||||
include/net/netns/conntrack.h | 3 +
|
||||
net/netfilter/Kconfig | 8 +++
|
||||
net/netfilter/nf_conntrack_core.c | 3 +
|
||||
net/netfilter/nf_conntrack_ecache.c | 67 +++++++++++++++++++++
|
||||
net/netfilter/nf_conntrack_netlink.c | 25 +++++++-
|
||||
6 files changed, 148 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/net/netfilter/nf_conntrack_ecache.h
|
||||
+++ b/include/net/netfilter/nf_conntrack_ecache.h
|
||||
@@ -65,13 +65,52 @@ struct nf_ct_event_notifier {
|
||||
int (*exp_event)(unsigned int events, const struct nf_exp_event *item);
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+extern int nf_conntrack_register_notifier(struct net *net,
|
||||
+ struct notifier_block *nb);
|
||||
+extern int nf_conntrack_unregister_notifier(struct net *net,
|
||||
+ struct notifier_block *nb);
|
||||
+static inline int
|
||||
+nf_conntrack_eventmask_report(unsigned int eventmask,
|
||||
+ struct nf_conn *ct,
|
||||
+ u32 portid,
|
||||
+ int report)
|
||||
+{
|
||||
+ struct nf_conntrack_ecache *e;
|
||||
+ struct net *net = nf_ct_net(ct);
|
||||
+
|
||||
+ e = nf_ct_ecache_find(ct);
|
||||
+ if (e == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (nf_ct_is_confirmed(ct)) {
|
||||
+ struct nf_ct_event item = {
|
||||
+ .ct = ct,
|
||||
+ .portid = e->portid ? e->portid : portid,
|
||||
+ .report = report
|
||||
+ };
|
||||
+ /* This is a resent of a destroy event? If so, skip missed */
|
||||
+ unsigned long missed = e->portid ? 0 : e->missed;
|
||||
+
|
||||
+ if (!((eventmask | missed) & e->ctmask))
|
||||
+ return 0;
|
||||
+
|
||||
+ atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
|
||||
+ eventmask | missed, &item);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#else
|
||||
void nf_conntrack_register_notifier(struct net *net,
|
||||
const struct nf_ct_event_notifier *nb);
|
||||
void nf_conntrack_unregister_notifier(struct net *net);
|
||||
|
||||
-void nf_ct_deliver_cached_events(struct nf_conn *ct);
|
||||
int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
|
||||
u32 portid, int report);
|
||||
+#endif
|
||||
+
|
||||
+void nf_ct_deliver_cached_events(struct nf_conn *ct);
|
||||
|
||||
bool nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp);
|
||||
#else
|
||||
@@ -98,11 +137,13 @@ static inline void
|
||||
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
- struct net *net = nf_ct_net(ct);
|
||||
struct nf_conntrack_ecache *e;
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ struct net *net = nf_ct_net(ct);
|
||||
|
||||
if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
|
||||
return;
|
||||
+#endif
|
||||
|
||||
e = nf_ct_ecache_find(ct);
|
||||
if (e == NULL)
|
||||
--- a/include/net/netns/conntrack.h
|
||||
+++ b/include/net/netns/conntrack.h
|
||||
@@ -104,6 +104,9 @@ struct netns_ct {
|
||||
u8 sysctl_checksum;
|
||||
|
||||
struct ip_conntrack_stat __percpu *stat;
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ struct atomic_notifier_head nf_conntrack_chain;
|
||||
+#endif
|
||||
struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
|
||||
struct nf_ip_net nf_ct_proto;
|
||||
#if defined(CONFIG_NF_CONNTRACK_LABELS)
|
||||
--- a/net/netfilter/Kconfig
|
||||
+++ b/net/netfilter/Kconfig
|
||||
@@ -181,6 +181,14 @@ config NF_CONNTRACK_DSCPREMARK_EXT
|
||||
This option enables support for connection tracking extension
|
||||
for dscp remark.
|
||||
|
||||
+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_core.c
|
||||
+++ b/net/netfilter/nf_conntrack_core.c
|
||||
@@ -2810,6 +2810,9 @@ int nf_conntrack_init_net(struct net *ne
|
||||
nf_conntrack_ecache_pernet_init(net);
|
||||
nf_conntrack_proto_pernet_init(net);
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ ATOMIC_INIT_NOTIFIER_HEAD(&net->ct.nf_conntrack_chain);
|
||||
+#endif
|
||||
return 0;
|
||||
|
||||
err_expect:
|
||||
--- a/net/netfilter/nf_conntrack_ecache.c
|
||||
+++ b/net/netfilter/nf_conntrack_ecache.c
|
||||
@@ -16,6 +16,9 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/err.h>
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+#include <linux/notifier.h>
|
||||
+#endif
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/slab.h>
|
||||
@@ -124,6 +127,7 @@ static void ecache_work(struct work_stru
|
||||
schedule_delayed_work(&cnet->ecache.dwork, delay);
|
||||
}
|
||||
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
static int __nf_conntrack_eventmask_report(struct nf_conntrack_ecache *e,
|
||||
const u32 events,
|
||||
const u32 missed,
|
||||
@@ -198,9 +202,56 @@ int nf_conntrack_eventmask_report(unsign
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report);
|
||||
+#endif
|
||||
|
||||
/* deliver cached events and clear cache entry - must be called with locally
|
||||
* disabled softirqs */
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+void nf_ct_deliver_cached_events(struct nf_conn *ct)
|
||||
+{
|
||||
+ unsigned long events, missed;
|
||||
+ struct nf_conntrack_ecache *e;
|
||||
+ struct nf_ct_event item;
|
||||
+ struct net *net = nf_ct_net(ct);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ e = nf_ct_ecache_find(ct);
|
||||
+ if (!e)
|
||||
+ return;
|
||||
+
|
||||
+ events = xchg(&e->cache, 0);
|
||||
+
|
||||
+ if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct) || !events)
|
||||
+ return;
|
||||
+
|
||||
+ /*
|
||||
+ * We make a copy of the missed event cache without taking
|
||||
+ * the lock, thus we may send missed events twice. However,
|
||||
+ * this does not harm and it happens very rarely.
|
||||
+ */
|
||||
+ missed = e->missed;
|
||||
+
|
||||
+ if (!((events | missed) & e->ctmask))
|
||||
+ return;
|
||||
+
|
||||
+ item.ct = ct;
|
||||
+ item.portid = 0;
|
||||
+ item.report = 0;
|
||||
+
|
||||
+ atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
|
||||
+ events | missed, &item);
|
||||
+
|
||||
+ if (likely(ret >= 0 && !missed))
|
||||
+ return;
|
||||
+
|
||||
+ spin_lock_bh(&ct->lock);
|
||||
+ if (ret < 0)
|
||||
+ e->missed |= events;
|
||||
+ else
|
||||
+ e->missed &= ~missed;
|
||||
+ spin_unlock_bh(&ct->lock);
|
||||
+}
|
||||
+#else
|
||||
void nf_ct_deliver_cached_events(struct nf_conn *ct)
|
||||
{
|
||||
struct nf_conntrack_ecache *e;
|
||||
@@ -226,6 +277,7 @@ void nf_ct_deliver_cached_events(struct
|
||||
*/
|
||||
__nf_conntrack_eventmask_report(e, events, e->missed, &item);
|
||||
}
|
||||
+#endif
|
||||
EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
|
||||
|
||||
void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
|
||||
@@ -258,6 +310,12 @@ out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb)
|
||||
+{
|
||||
+ return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
|
||||
+}
|
||||
+#else
|
||||
void nf_conntrack_register_notifier(struct net *net,
|
||||
const struct nf_ct_event_notifier *new)
|
||||
{
|
||||
@@ -270,8 +328,16 @@ void nf_conntrack_register_notifier(stru
|
||||
rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new);
|
||||
mutex_unlock(&nf_ct_ecache_mutex);
|
||||
}
|
||||
+#endif
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb)
|
||||
+{
|
||||
+ return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain,
|
||||
+ nb);
|
||||
+}
|
||||
+#else
|
||||
void nf_conntrack_unregister_notifier(struct net *net)
|
||||
{
|
||||
mutex_lock(&nf_ct_ecache_mutex);
|
||||
@@ -279,6 +345,7 @@ void nf_conntrack_unregister_notifier(st
|
||||
mutex_unlock(&nf_ct_ecache_mutex);
|
||||
/* synchronize_rcu() is called after netns pre_exit */
|
||||
}
|
||||
+#endif
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
|
||||
|
||||
void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state)
|
||||
--- a/net/netfilter/nf_conntrack_netlink.c
|
||||
+++ b/net/netfilter/nf_conntrack_netlink.c
|
||||
@@ -28,6 +28,9 @@
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+#include <linux/notifier.h>
|
||||
+#endif
|
||||
#include <linux/slab.h>
|
||||
#include <linux/siphash.h>
|
||||
|
||||
@@ -719,18 +722,26 @@ static size_t ctnetlink_nlmsg_size(const
|
||||
;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+static int ctnetlink_conntrack_event(struct notifier_block *this,
|
||||
+ unsigned long events, void *ptr)
|
||||
+#else
|
||||
static int
|
||||
ctnetlink_conntrack_event(unsigned int events, const struct nf_ct_event *item)
|
||||
+#endif
|
||||
{
|
||||
const struct nf_conntrack_zone *zone;
|
||||
struct net *net;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nlattr *nest_parms;
|
||||
- struct nf_conn *ct = item->ct;
|
||||
struct sk_buff *skb;
|
||||
unsigned int type;
|
||||
unsigned int flags = 0, group;
|
||||
int err;
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ struct nf_ct_event *item = (struct nf_ct_event *)ptr;
|
||||
+#endif
|
||||
+ struct nf_conn *ct = item->ct;
|
||||
|
||||
if (events & (1 << IPCT_DESTROY)) {
|
||||
type = IPCTNL_MSG_CT_DELETE;
|
||||
@@ -3089,6 +3100,7 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
static int
|
||||
ctnetlink_expect_event(unsigned int events, const struct nf_exp_event *item)
|
||||
{
|
||||
@@ -3138,6 +3150,7 @@ errout:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
+#endif
|
||||
static int ctnetlink_exp_done(struct netlink_callback *cb)
|
||||
{
|
||||
if (cb->args[1])
|
||||
@@ -3748,11 +3761,17 @@ static int ctnetlink_stat_exp_cpu(struct
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+static struct notifier_block ctnl_notifier = {
|
||||
+ .notifier_call = ctnetlink_conntrack_event,
|
||||
+};
|
||||
+#else
|
||||
static struct nf_ct_event_notifier ctnl_notifier = {
|
||||
.ct_event = ctnetlink_conntrack_event,
|
||||
.exp_event = ctnetlink_expect_event,
|
||||
};
|
||||
#endif
|
||||
+#endif
|
||||
|
||||
static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
|
||||
[IPCTNL_MSG_CT_NEW] = {
|
||||
@@ -3851,8 +3870,12 @@ static int __net_init ctnetlink_net_init
|
||||
static void ctnetlink_net_pre_exit(struct net *net)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
|
||||
+ nf_conntrack_unregister_notifier(net, &ctnl_notifier);
|
||||
+#else
|
||||
nf_conntrack_unregister_notifier(net);
|
||||
#endif
|
||||
+#endif
|
||||
}
|
||||
|
||||
static struct pernet_operations ctnetlink_net_ops = {
|
||||
@@ -0,0 +1,720 @@
|
||||
From 691195eec4f741a2e73accae97092cf0a0203a54 Mon Sep 17 00:00:00 2001
|
||||
From: Ratheesh Kannoth <rkannoth@codeaurora.org>
|
||||
Date: Fri, 15 May 2020 12:36:11 +0530
|
||||
Subject: [PATCH] net/bonding: Added acceleration support over LAG interface
|
||||
|
||||
The accel support is enabled for the following LAG modes,
|
||||
1. Balance-Xor (Static LAG)
|
||||
2. 802.3ad (Dynamic LAG)
|
||||
Change-Id: I4524902ddec583a2963cb38731c062f216a5386d
|
||||
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
|
||||
|
||||
net/bonding: Fix for Load Balancing within bonding (LAG) group
|
||||
|
||||
New APIs (without skb) introduced in bonding driver to calculate hash on given
|
||||
parameters (IP version, src IP, dst IP, src MAC, dst MAC) has issue in creating
|
||||
flow_key. flow_get_u32_dst is returning 0 for given flow_key because addr_type
|
||||
is not set correctly. Fix is added to populate addr_type. Test different flows
|
||||
and verified that the flows are distributed.
|
||||
|
||||
Change-Id: Ie54a40f590010ea2994ffc4ace8f4d050258a06f
|
||||
Signed-off-by: Bhaskar Valaboju <bhaskarv@codeaurora.org>
|
||||
Signed-off-by: Ratheesh Kannoth <rkannoth@codeaurora.org>
|
||||
|
||||
net: bonding: Relocate kernel bond functions
|
||||
|
||||
header files included in uapi folder are the interface between
|
||||
userspace and kernel space. This path declares new bonding
|
||||
functions in kernel header file instead of uapi header file.
|
||||
|
||||
Change-Id: I1b33f07015b79ec4ac702a9079da01f1c2a08bbb
|
||||
Signed-off-by: Ratheesh Kannoth <rkannoth@codeaurora.org>
|
||||
---
|
||||
drivers/net/bonding/bond_3ad.c | 160 ++++++++++++++++-
|
||||
drivers/net/bonding/bond_main.c | 306 ++++++++++++++++++++++++++++++--
|
||||
include/net/bond_3ad.h | 7 +-
|
||||
include/net/bonding.h | 21 +++
|
||||
4 files changed, 481 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/bonding/bond_3ad.c
|
||||
+++ b/drivers/net/bonding/bond_3ad.c
|
||||
@@ -116,6 +116,38 @@ static void ad_marker_response_received(
|
||||
struct port *port);
|
||||
static void ad_update_actor_keys(struct port *port, bool reset);
|
||||
|
||||
+struct bond_cb __rcu *bond_cb;
|
||||
+
|
||||
+int bond_register_cb(struct bond_cb *cb)
|
||||
+{
|
||||
+ struct bond_cb *lag_cb;
|
||||
+
|
||||
+ lag_cb = kzalloc(sizeof(*lag_cb), GFP_ATOMIC | __GFP_NOWARN);
|
||||
+ if (!lag_cb) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ memcpy((void *)lag_cb, (void *)cb, sizeof(*cb));
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ rcu_assign_pointer(bond_cb, lag_cb);
|
||||
+ rcu_read_unlock();
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(bond_register_cb);
|
||||
+
|
||||
+void bond_unregister_cb(void)
|
||||
+{
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+ rcu_assign_pointer(bond_cb, NULL);
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ kfree(lag_cb_main);
|
||||
+}
|
||||
+EXPORT_SYMBOL(bond_unregister_cb);
|
||||
|
||||
/* ================= api to bonding and kernel code ================== */
|
||||
|
||||
@@ -1073,6 +1105,28 @@ static void ad_mux_machine(struct port *
|
||||
ad_disable_collecting_distributing(port,
|
||||
update_slave_arr);
|
||||
port->ntt = true;
|
||||
+
|
||||
+ /* Send a notificaton about change in state of this
|
||||
+ * port. We only want to handle case where port moves
|
||||
+ * from AD_MUX_COLLECTING_DISTRIBUTING ->
|
||||
+ * AD_MUX_ATTACHED.
|
||||
+ */
|
||||
+ if (bond_slave_is_up(port->slave) &&
|
||||
+ (last_state == AD_MUX_COLLECTING_DISTRIBUTING)) {
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+ if (lag_cb_main &&
|
||||
+ lag_cb_main->bond_cb_link_down) {
|
||||
+ struct net_device *dev;
|
||||
+
|
||||
+ dev = port->slave->dev;
|
||||
+ lag_cb_main->bond_cb_link_down(dev);
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+
|
||||
break;
|
||||
case AD_MUX_COLLECTING_DISTRIBUTING:
|
||||
port->actor_oper_port_state |= LACP_STATE_COLLECTING;
|
||||
@@ -1917,6 +1971,7 @@ static void ad_enable_collecting_distrib
|
||||
bool *update_slave_arr)
|
||||
{
|
||||
if (port->aggregator->is_active) {
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
slave_dbg(port->slave->bond->dev, port->slave->dev,
|
||||
"Enabling port %d (LAG %d)\n",
|
||||
port->actor_port_number,
|
||||
@@ -1924,6 +1979,14 @@ static void ad_enable_collecting_distrib
|
||||
__enable_port(port);
|
||||
/* Slave array needs update */
|
||||
*update_slave_arr = true;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+
|
||||
+ if (lag_cb_main && lag_cb_main->bond_cb_link_up)
|
||||
+ lag_cb_main->bond_cb_link_up(port->slave->dev);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2683,6 +2746,102 @@ int bond_3ad_get_active_agg_info(struct
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* bond_3ad_get_tx_dev - Calculate egress interface for a given packet,
|
||||
+ * for a LAG that is configured in 802.3AD mode
|
||||
+ * @skb: pointer to skb to be egressed
|
||||
+ * @src_mac: pointer to source L2 address
|
||||
+ * @dst_mac: pointer to destination L2 address
|
||||
+ * @src: pointer to source L3 address
|
||||
+ * @dst: pointer to destination L3 address
|
||||
+ * @protocol: L3 protocol id from L2 header
|
||||
+ * @bond_dev: pointer to bond master device
|
||||
+ *
|
||||
+ * If @skb is NULL, bond_xmit_hash is used to calculate hash using L2/L3
|
||||
+ * addresses.
|
||||
+ *
|
||||
+ * Returns: Either valid slave device, or NULL otherwise
|
||||
+ */
|
||||
+struct net_device *bond_3ad_get_tx_dev(struct sk_buff *skb, u8 *src_mac,
|
||||
+ u8 *dst_mac, void *src,
|
||||
+ void *dst, u16 protocol,
|
||||
+ struct net_device *bond_dev,
|
||||
+ __be16 *layer4hdr)
|
||||
+{
|
||||
+ struct bonding *bond = netdev_priv(bond_dev);
|
||||
+ struct aggregator *agg;
|
||||
+ struct ad_info ad_info;
|
||||
+ struct list_head *iter;
|
||||
+ struct slave *slave;
|
||||
+ struct slave *first_ok_slave = NULL;
|
||||
+ u32 hash = 0;
|
||||
+ int slaves_in_agg;
|
||||
+ int slave_agg_no = 0;
|
||||
+ int agg_id;
|
||||
+
|
||||
+ if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
|
||||
+ pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
|
||||
+ bond_dev->name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ slaves_in_agg = ad_info.ports;
|
||||
+ agg_id = ad_info.aggregator_id;
|
||||
+
|
||||
+ if (slaves_in_agg == 0) {
|
||||
+ pr_debug("%s: Error: active aggregator is empty\n",
|
||||
+ bond_dev->name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (skb) {
|
||||
+ hash = bond_xmit_hash(bond, skb);
|
||||
+ slave_agg_no = hash % slaves_in_agg;
|
||||
+ } else {
|
||||
+ if (bond->params.xmit_policy != BOND_XMIT_POLICY_LAYER23 &&
|
||||
+ bond->params.xmit_policy != BOND_XMIT_POLICY_LAYER2 &&
|
||||
+ bond->params.xmit_policy != BOND_XMIT_POLICY_LAYER34) {
|
||||
+ pr_debug("%s: Error: Unsupported hash policy for 802.3AD fast path\n",
|
||||
+ bond_dev->name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ hash = bond_xmit_hash_without_skb(src_mac, dst_mac,
|
||||
+ src, dst, protocol,
|
||||
+ bond_dev, layer4hdr);
|
||||
+ slave_agg_no = hash % slaves_in_agg;
|
||||
+ }
|
||||
+
|
||||
+ bond_for_each_slave_rcu(bond, slave, iter) {
|
||||
+ agg = SLAVE_AD_INFO(slave)->port.aggregator;
|
||||
+ if (!agg || agg->aggregator_identifier != agg_id)
|
||||
+ continue;
|
||||
+
|
||||
+ if (slave_agg_no >= 0) {
|
||||
+ if (!first_ok_slave && bond_slave_can_tx(slave))
|
||||
+ first_ok_slave = slave;
|
||||
+ slave_agg_no--;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (bond_slave_can_tx(slave))
|
||||
+ return slave->dev;
|
||||
+ }
|
||||
+
|
||||
+ if (slave_agg_no >= 0) {
|
||||
+ pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n",
|
||||
+ bond_dev->name, agg_id);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* we couldn't find any suitable slave after the agg_no, so use the
|
||||
+ * first suitable found, if found.
|
||||
+ */
|
||||
+ if (first_ok_slave)
|
||||
+ return first_ok_slave->dev;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
|
||||
struct slave *slave)
|
||||
{
|
||||
--- a/drivers/net/bonding/bond_main.c
|
||||
+++ b/drivers/net/bonding/bond_main.c
|
||||
@@ -210,6 +210,7 @@ atomic_t netpoll_block_tx = ATOMIC_INIT(
|
||||
#endif
|
||||
|
||||
unsigned int bond_net_id __read_mostly;
|
||||
+static unsigned long bond_id_mask = 0xFFFFFFF0;
|
||||
|
||||
static const struct flow_dissector_key flow_keys_bonding_keys[] = {
|
||||
{
|
||||
@@ -287,6 +288,19 @@ const char *bond_mode_name(int mode)
|
||||
return names[mode];
|
||||
}
|
||||
|
||||
+int bond_get_id(struct net_device *bond_dev)
|
||||
+{
|
||||
+ struct bonding *bond;
|
||||
+
|
||||
+ if (!((bond_dev->priv_flags & IFF_BONDING) &&
|
||||
+ (bond_dev->flags & IFF_MASTER)))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ bond = netdev_priv(bond_dev);
|
||||
+ return bond->id;
|
||||
+}
|
||||
+EXPORT_SYMBOL(bond_get_id);
|
||||
+
|
||||
/**
|
||||
* bond_dev_queue_xmit - Prepare skb for xmit.
|
||||
*
|
||||
@@ -1231,6 +1245,21 @@ void bond_change_active_slave(struct bon
|
||||
if (BOND_MODE(bond) == BOND_MODE_8023AD)
|
||||
bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
|
||||
|
||||
+ if (bond->params.mode == BOND_MODE_XOR) {
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+ if (lag_cb_main &&
|
||||
+ lag_cb_main->bond_cb_link_up) {
|
||||
+ struct net_device *dev;
|
||||
+
|
||||
+ dev = new_active->dev;
|
||||
+ lag_cb_main->bond_cb_link_up(dev);
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+ }
|
||||
+
|
||||
if (bond_is_lb(bond))
|
||||
bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
|
||||
} else {
|
||||
@@ -1876,6 +1905,7 @@ int bond_enslave(struct net_device *bond
|
||||
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
|
||||
struct slave *new_slave = NULL, *prev_slave;
|
||||
struct sockaddr_storage ss;
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
int link_reporting;
|
||||
int res = 0, i;
|
||||
|
||||
@@ -2325,6 +2355,13 @@ int bond_enslave(struct net_device *bond
|
||||
bond_is_active_slave(new_slave) ? "an active" : "a backup",
|
||||
new_slave->link != BOND_LINK_DOWN ? "an up" : "a down");
|
||||
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+ if (lag_cb_main && lag_cb_main->bond_cb_enslave)
|
||||
+ lag_cb_main->bond_cb_enslave(slave_dev);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
/* enslave is successful */
|
||||
bond_queue_slave_event(new_slave);
|
||||
return 0;
|
||||
@@ -2390,6 +2427,13 @@ err_undo_flags:
|
||||
}
|
||||
}
|
||||
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+ if (lag_cb_main && lag_cb_main->bond_cb_enslave)
|
||||
+ lag_cb_main->bond_cb_enslave(slave_dev);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2411,6 +2455,7 @@ static int __bond_release_one(struct net
|
||||
struct bonding *bond = netdev_priv(bond_dev);
|
||||
struct slave *slave, *oldcurrent;
|
||||
struct sockaddr_storage ss;
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
int old_flags = bond_dev->flags;
|
||||
netdev_features_t old_features = bond_dev->features;
|
||||
|
||||
@@ -2433,6 +2478,13 @@ static int __bond_release_one(struct net
|
||||
|
||||
bond_set_slave_inactive_flags(slave, BOND_SLAVE_NOTIFY_NOW);
|
||||
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+ if (lag_cb_main && lag_cb_main->bond_cb_release)
|
||||
+ lag_cb_main->bond_cb_release(slave_dev);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
bond_sysfs_slave_del(slave);
|
||||
|
||||
/* recompute stats just before removing the slave */
|
||||
@@ -2761,8 +2813,8 @@ static void bond_miimon_commit(struct bo
|
||||
struct slave *slave, *primary, *active;
|
||||
bool do_failover = false;
|
||||
struct list_head *iter;
|
||||
-
|
||||
- ASSERT_RTNL();
|
||||
+ struct net_device *slave_dev = NULL;
|
||||
+ struct bond_cb *lag_cb_main;
|
||||
|
||||
bond_for_each_slave(bond, slave, iter) {
|
||||
switch (slave->link_new_state) {
|
||||
@@ -2800,6 +2852,10 @@ static void bond_miimon_commit(struct bo
|
||||
bond_set_active_slave(slave);
|
||||
}
|
||||
|
||||
+ if ((bond->params.mode == BOND_MODE_XOR) &&
|
||||
+ (!slave_dev))
|
||||
+ slave_dev = slave->dev;
|
||||
+
|
||||
slave_info(bond->dev, slave->dev, "link status definitely up, %u Mbps %s duplex\n",
|
||||
slave->speed == SPEED_UNKNOWN ? 0 : slave->speed,
|
||||
slave->duplex ? "full" : "half");
|
||||
@@ -2848,6 +2904,14 @@ static void bond_miimon_commit(struct bo
|
||||
unblock_netpoll_tx();
|
||||
}
|
||||
|
||||
+ rcu_read_lock();
|
||||
+ lag_cb_main = rcu_dereference(bond_cb);
|
||||
+
|
||||
+ if (slave_dev && lag_cb_main && lag_cb_main->bond_cb_link_up)
|
||||
+ lag_cb_main->bond_cb_link_up(slave_dev);
|
||||
+
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
bond_set_carrier(bond);
|
||||
}
|
||||
|
||||
@@ -4100,7 +4164,216 @@ static inline u32 bond_eth_hash(struct s
|
||||
return 0;
|
||||
|
||||
ep = (struct ethhdr *)(data + mhoff);
|
||||
- return ep->h_dest[5] ^ ep->h_source[5] ^ be16_to_cpu(ep->h_proto);
|
||||
+ return ep->h_dest[5] ^ ep->h_source[5];
|
||||
+}
|
||||
+
|
||||
+/* Extract the appropriate headers based on bond's xmit policy */
|
||||
+static bool bond_flow_dissect_without_skb(struct bonding *bond,
|
||||
+ u8 *src_mac, u8 *dst_mac,
|
||||
+ void *psrc, void *pdst,
|
||||
+ u16 protocol, __be16 *layer4hdr,
|
||||
+ struct flow_keys *fk)
|
||||
+{
|
||||
+ u32 *src = NULL;
|
||||
+ u32 *dst = NULL;
|
||||
+
|
||||
+ fk->ports.ports = 0;
|
||||
+ src = (uint32_t *)psrc;
|
||||
+ dst = (uint32_t *)pdst;
|
||||
+
|
||||
+ if (protocol == htons(ETH_P_IP)) {
|
||||
+ /* V4 addresses and address type*/
|
||||
+ fk->addrs.v4addrs.src = src[0];
|
||||
+ fk->addrs.v4addrs.dst = dst[0];
|
||||
+ fk->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS;
|
||||
+ } else if (protocol == htons(ETH_P_IPV6)) {
|
||||
+ /* V6 addresses and address type*/
|
||||
+ memcpy(&fk->addrs.v6addrs.src, src, sizeof(struct in6_addr));
|
||||
+ memcpy(&fk->addrs.v6addrs.dst, dst, sizeof(struct in6_addr));
|
||||
+ fk->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ if ((bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) &&
|
||||
+ (layer4hdr))
|
||||
+ fk->ports.ports = *layer4hdr;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+/* bond_xmit_hash_without_skb - Applies load balancing algorithm for a packet,
|
||||
+ * to calculate hash for a given set of L2/L3 addresses. Does not
|
||||
+ * calculate egress interface.
|
||||
+ */
|
||||
+uint32_t bond_xmit_hash_without_skb(u8 *src_mac, u8 *dst_mac,
|
||||
+ void *psrc, void *pdst, u16 protocol,
|
||||
+ struct net_device *bond_dev,
|
||||
+ __be16 *layer4hdr)
|
||||
+{
|
||||
+ struct bonding *bond = netdev_priv(bond_dev);
|
||||
+ struct flow_keys flow;
|
||||
+ u32 hash = 0;
|
||||
+
|
||||
+ if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER2 ||
|
||||
+ !bond_flow_dissect_without_skb(bond, src_mac, dst_mac, psrc,
|
||||
+ pdst, protocol, layer4hdr, &flow))
|
||||
+ return (dst_mac[5] ^ src_mac[5]);
|
||||
+
|
||||
+ if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER23)
|
||||
+ hash = dst_mac[5] ^ src_mac[5];
|
||||
+ else if (layer4hdr)
|
||||
+ hash = (__force u32)flow.ports.ports;
|
||||
+
|
||||
+ hash ^= (__force u32)flow_get_u32_dst(&flow) ^
|
||||
+ (__force u32)flow_get_u32_src(&flow);
|
||||
+ hash ^= (hash >> 16);
|
||||
+ hash ^= (hash >> 8);
|
||||
+
|
||||
+ return hash;
|
||||
+}
|
||||
+
|
||||
+/* bond_xor_get_tx_dev - Calculate egress interface for a given packet for a LAG
|
||||
+ * that is configured in balance-xor mode
|
||||
+ * @skb: pointer to skb to be egressed
|
||||
+ * @src_mac: pointer to source L2 address
|
||||
+ * @dst_mac: pointer to destination L2 address
|
||||
+ * @src: pointer to source L3 address in network order
|
||||
+ * @dst: pointer to destination L3 address in network order
|
||||
+ * @protocol: L3 protocol
|
||||
+ * @bond_dev: pointer to bond master device
|
||||
+ *
|
||||
+ * If @skb is NULL, bond_xmit_hash_without_skb is used to calculate hash using
|
||||
+ * L2/L3 addresses.
|
||||
+ *
|
||||
+ * Returns: Either valid slave device, or NULL otherwise
|
||||
+ */
|
||||
+static struct net_device *bond_xor_get_tx_dev(struct sk_buff *skb,
|
||||
+ u8 *src_mac, u8 *dst_mac,
|
||||
+ void *src, void *dst,
|
||||
+ u16 protocol,
|
||||
+ struct net_device *bond_dev,
|
||||
+ __be16 *layer4hdr)
|
||||
+{
|
||||
+ struct bonding *bond = netdev_priv(bond_dev);
|
||||
+ int slave_cnt = READ_ONCE(bond->slave_cnt);
|
||||
+ int slave_id = 0, i = 0;
|
||||
+ u32 hash;
|
||||
+ struct list_head *iter;
|
||||
+ struct slave *slave;
|
||||
+
|
||||
+ if (slave_cnt == 0) {
|
||||
+ pr_debug("%s: Error: No slave is attached to the interface\n",
|
||||
+ bond_dev->name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (skb) {
|
||||
+ hash = bond_xmit_hash(bond, skb);
|
||||
+ slave_id = hash % slave_cnt;
|
||||
+ } else {
|
||||
+ if (bond->params.xmit_policy != BOND_XMIT_POLICY_LAYER23 &&
|
||||
+ bond->params.xmit_policy != BOND_XMIT_POLICY_LAYER2 &&
|
||||
+ bond->params.xmit_policy != BOND_XMIT_POLICY_LAYER34) {
|
||||
+ pr_debug("%s: Error: Unsupported hash policy for balance-XOR fast path\n",
|
||||
+ bond_dev->name);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ hash = bond_xmit_hash_without_skb(src_mac, dst_mac, src,
|
||||
+ dst, protocol, bond_dev,
|
||||
+ layer4hdr);
|
||||
+ slave_id = hash % slave_cnt;
|
||||
+ }
|
||||
+
|
||||
+ i = slave_id;
|
||||
+
|
||||
+ /* Here we start from the slave with slave_id */
|
||||
+ bond_for_each_slave_rcu(bond, slave, iter) {
|
||||
+ if (--i < 0) {
|
||||
+ if (bond_slave_can_tx(slave))
|
||||
+ return slave->dev;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Here we start from the first slave up to slave_id */
|
||||
+ i = slave_id;
|
||||
+ bond_for_each_slave_rcu(bond, slave, iter) {
|
||||
+ if (--i < 0)
|
||||
+ break;
|
||||
+ if (bond_slave_can_tx(slave))
|
||||
+ return slave->dev;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/* bond_get_tx_dev - Calculate egress interface for a given packet.
|
||||
+ *
|
||||
+ * Supports 802.3AD and balance-xor modes
|
||||
+ *
|
||||
+ * @skb: pointer to skb to be egressed, if valid
|
||||
+ * @src_mac: pointer to source L2 address
|
||||
+ * @dst_mac: pointer to destination L2 address
|
||||
+ * @src: pointer to source L3 address in network order
|
||||
+ * @dst: pointer to destination L3 address in network order
|
||||
+ * @protocol: L3 protocol id from L2 header
|
||||
+ * @bond_dev: pointer to bond master device
|
||||
+ *
|
||||
+ * Returns: Either valid slave device, or NULL for un-supported LAG modes
|
||||
+ */
|
||||
+struct net_device *bond_get_tx_dev(struct sk_buff *skb, uint8_t *src_mac,
|
||||
+ u8 *dst_mac, void *src,
|
||||
+ void *dst, u16 protocol,
|
||||
+ struct net_device *bond_dev,
|
||||
+ __be16 *layer4hdr)
|
||||
+{
|
||||
+ struct bonding *bond;
|
||||
+
|
||||
+ if (!bond_dev)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!((bond_dev->priv_flags & IFF_BONDING) &&
|
||||
+ (bond_dev->flags & IFF_MASTER)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ bond = netdev_priv(bond_dev);
|
||||
+
|
||||
+ switch (bond->params.mode) {
|
||||
+ case BOND_MODE_XOR:
|
||||
+ return bond_xor_get_tx_dev(skb, src_mac, dst_mac,
|
||||
+ src, dst, protocol,
|
||||
+ bond_dev, layer4hdr);
|
||||
+ case BOND_MODE_8023AD:
|
||||
+ return bond_3ad_get_tx_dev(skb, src_mac, dst_mac,
|
||||
+ src, dst, protocol,
|
||||
+ bond_dev, layer4hdr);
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL(bond_get_tx_dev);
|
||||
+
|
||||
+/* In bond_xmit_xor() , we determine the output device by using a pre-
|
||||
+ * determined xmit_hash_policy(), If the selected device is not enabled,
|
||||
+ * find the next active slave.
|
||||
+ */
|
||||
+static int bond_xmit_xor(struct sk_buff *skb, struct net_device *dev)
|
||||
+{
|
||||
+ struct bonding *bond = netdev_priv(dev);
|
||||
+ struct net_device *outdev;
|
||||
+
|
||||
+ outdev = bond_xor_get_tx_dev(skb, NULL, NULL, NULL,
|
||||
+ NULL, 0, dev, NULL);
|
||||
+ if (!outdev)
|
||||
+ goto out;
|
||||
+
|
||||
+ bond_dev_queue_xmit(bond, skb, outdev);
|
||||
+ goto final;
|
||||
+out:
|
||||
+ /* no suitable interface, frame not sent */
|
||||
+ dev_kfree_skb(skb);
|
||||
+final:
|
||||
+ return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static bool bond_flow_ip(struct sk_buff *skb, struct flow_keys *fk, const void *data,
|
||||
@@ -5230,15 +5503,16 @@ static netdev_tx_t bond_3ad_xor_xmit(str
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct bonding *bond = netdev_priv(dev);
|
||||
- struct bond_up_slave *slaves;
|
||||
- struct slave *slave;
|
||||
+ struct net_device *outdev = NULL;
|
||||
|
||||
- slaves = rcu_dereference(bond->usable_slaves);
|
||||
- slave = bond_xmit_3ad_xor_slave_get(bond, skb, slaves);
|
||||
- if (likely(slave))
|
||||
- return bond_dev_queue_xmit(bond, skb, slave->dev);
|
||||
+ outdev = bond_3ad_get_tx_dev(skb, NULL, NULL, NULL,
|
||||
+ NULL, 0, dev, NULL);
|
||||
+ if (!outdev) {
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return NETDEV_TX_OK;
|
||||
+ }
|
||||
|
||||
- return bond_tx_drop(dev, skb);
|
||||
+ return bond_dev_queue_xmit(bond, skb, outdev);
|
||||
}
|
||||
|
||||
/* in broadcast mode, we send everything to all usable interfaces. */
|
||||
@@ -5488,8 +5762,9 @@ static netdev_tx_t __bond_start_xmit(str
|
||||
return bond_xmit_roundrobin(skb, dev);
|
||||
case BOND_MODE_ACTIVEBACKUP:
|
||||
return bond_xmit_activebackup(skb, dev);
|
||||
- case BOND_MODE_8023AD:
|
||||
case BOND_MODE_XOR:
|
||||
+ return bond_xmit_xor(skb, dev);
|
||||
+ case BOND_MODE_8023AD:
|
||||
return bond_3ad_xor_xmit(skb, dev);
|
||||
case BOND_MODE_BROADCAST:
|
||||
return bond_xmit_broadcast(skb, dev);
|
||||
@@ -5926,6 +6201,9 @@ static void bond_destructor(struct net_d
|
||||
if (bond->wq)
|
||||
destroy_workqueue(bond->wq);
|
||||
|
||||
+ if (bond->id != (~0U))
|
||||
+ clear_bit(bond->id, &bond_id_mask);
|
||||
+
|
||||
free_percpu(bond->rr_tx_counter);
|
||||
}
|
||||
|
||||
@@ -6479,6 +6757,11 @@ int bond_create(struct net *net, const c
|
||||
|
||||
bond_work_init_all(bond);
|
||||
|
||||
+ bond->id = ~0U;
|
||||
+ if (bond_id_mask != (~0UL)) {
|
||||
+ bond->id = (u32)ffz(bond_id_mask);
|
||||
+ set_bit(bond->id, &bond_id_mask);
|
||||
+ }
|
||||
out:
|
||||
rtnl_unlock();
|
||||
return res;
|
||||
--- a/include/net/bond_3ad.h
|
||||
+++ b/include/net/bond_3ad.h
|
||||
@@ -302,6 +302,12 @@ int bond_3ad_lacpdu_recv(const struct sk
|
||||
struct slave *slave);
|
||||
int bond_3ad_set_carrier(struct bonding *bond);
|
||||
void bond_3ad_update_lacp_rate(struct bonding *bond);
|
||||
+struct net_device *bond_3ad_get_tx_dev(struct sk_buff *skb, uint8_t *src_mac,
|
||||
+ uint8_t *dst_mac, void *src,
|
||||
+ void *dst, uint16_t protocol,
|
||||
+ struct net_device *bond_dev,
|
||||
+ __be16 *layer4hdr);
|
||||
+
|
||||
void bond_3ad_update_ad_actor_settings(struct bonding *bond);
|
||||
int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats);
|
||||
size_t bond_3ad_stats_size(void);
|
||||
--- a/include/net/bonding.h
|
||||
+++ b/include/net/bonding.h
|
||||
@@ -90,6 +90,8 @@
|
||||
#define BOND_XFRM_FEATURES (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM | \
|
||||
NETIF_F_GSO_ESP)
|
||||
|
||||
+extern struct bond_cb __rcu *bond_cb;
|
||||
+
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
extern atomic_t netpoll_block_tx;
|
||||
|
||||
@@ -261,6 +263,7 @@ struct bonding {
|
||||
struct mutex ipsec_lock;
|
||||
#endif /* CONFIG_XFRM_OFFLOAD */
|
||||
struct bpf_prog *xdp_prog;
|
||||
+ u32 id;
|
||||
};
|
||||
|
||||
#define bond_slave_get_rcu(dev) \
|
||||
@@ -683,6 +686,11 @@ struct bond_vlan_tag *bond_verify_device
|
||||
int level);
|
||||
int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
|
||||
void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay);
|
||||
+uint32_t bond_xmit_hash_without_skb(uint8_t *src_mac, uint8_t *dst_mac,
|
||||
+ void *psrc, void *pdst, uint16_t protocol,
|
||||
+ struct net_device *bond_dev,
|
||||
+ __be16 *layer4hdr);
|
||||
+
|
||||
void bond_work_init_all(struct bonding *bond);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
@@ -787,4 +795,17 @@ static inline netdev_tx_t bond_tx_drop(s
|
||||
return NET_XMIT_DROP;
|
||||
}
|
||||
|
||||
+struct bond_cb {
|
||||
+ void (*bond_cb_link_up)(struct net_device *slave);
|
||||
+ void (*bond_cb_link_down)(struct net_device *slave);
|
||||
+ void (*bond_cb_enslave)(struct net_device *slave);
|
||||
+ void (*bond_cb_release)(struct net_device *slave);
|
||||
+ void (*bond_cb_delete_by_slave)(struct net_device *slave);
|
||||
+ void (*bond_cb_delete_by_mac)(uint8_t *mac_addr);
|
||||
+};
|
||||
+
|
||||
+extern int bond_register_cb(struct bond_cb *cb);
|
||||
+extern void bond_unregister_cb(void);
|
||||
+extern int bond_get_id(struct net_device *bond_dev);
|
||||
+
|
||||
#endif /* _NET_BONDING_H */
|
||||
@@ -0,0 +1,10 @@
|
||||
--- a/net/netfilter/nf_conntrack_ecache.c
|
||||
+++ b/net/netfilter/nf_conntrack_ecache.c
|
||||
@@ -324,7 +324,6 @@ void nf_conntrack_register_notifier(stru
|
||||
mutex_lock(&nf_ct_ecache_mutex);
|
||||
notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb,
|
||||
lockdep_is_held(&nf_ct_ecache_mutex));
|
||||
- WARN_ON_ONCE(notify);
|
||||
rcu_assign_pointer(net->ct.nf_conntrack_event_cb, new);
|
||||
mutex_unlock(&nf_ct_ecache_mutex);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
From 337dafaa0d7bf49e25b4ec74ff44ca697abd06bc Mon Sep 17 00:00:00 2001
|
||||
From: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
Date: Tue, 2 May 2023 21:39:54 -0700
|
||||
Subject: [PATCH 213/281] bridge: fix bridge vlan filter toggle issue
|
||||
|
||||
when vlan filter is disabled, it could cause new bridge
|
||||
creation failed if vlan filter setting existing in the
|
||||
netlink creation message
|
||||
|
||||
Change-Id: I02f010e746e94623fda544846d05908a83d14fa2
|
||||
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
---
|
||||
net/bridge/br_netlink.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/net/bridge/br_netlink.c
|
||||
+++ b/net/bridge/br_netlink.c
|
||||
@@ -1320,6 +1320,7 @@ static int br_changelink(struct net_devi
|
||||
br_stp_set_bridge_priority(br, priority);
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_BRIDGE_VLAN_FILTERING
|
||||
if (data[IFLA_BR_VLAN_FILTERING]) {
|
||||
u8 vlan_filter = nla_get_u8(data[IFLA_BR_VLAN_FILTERING]);
|
||||
|
||||
@@ -1328,7 +1329,6 @@ static int br_changelink(struct net_devi
|
||||
return err;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_BRIDGE_VLAN_FILTERING
|
||||
if (data[IFLA_BR_VLAN_PROTOCOL]) {
|
||||
__be16 vlan_proto = nla_get_be16(data[IFLA_BR_VLAN_PROTOCOL]);
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
From b5f89637414ada5125cbc9138f5b27cbfa8fe1b5 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
Date: Wed, 10 May 2023 13:15:19 -0700
|
||||
Subject: [PATCH 219/281] bridge: Add new bridge APIs needed for network HW
|
||||
acceleration
|
||||
|
||||
Bridge acceleration hardware needs to perform certain operations,
|
||||
currently unsupported by the existing bridge code:
|
||||
*given a certain bridge device and a MAC@, figure out on
|
||||
which underlying slave port this MAC@ is located
|
||||
*trigger an FDB entry refresh from outside the bridge code: packets will
|
||||
not be seen anymore in the host, once a flow has been accelerated.
|
||||
So the hardware accelerator driver needs to keep track of the accelerated
|
||||
flows and refresh the MACs accordingly.
|
||||
*update bridge interface statistics from outside the bridge code:
|
||||
once acceleration is enabled on a connection, packets will not flow
|
||||
through the host CPU, so we need the hardware accelerator driver to
|
||||
maintain the statistics on the host and update them and add whatever
|
||||
flows through the hardware.
|
||||
These change adds the corresponding functions, and make it available
|
||||
to other through EXPORT_SYMBOLS().
|
||||
|
||||
Change-Id: I67afb325796004053897d9916e2df91827b65139
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
|
||||
net: bridge: Rework APIs added for network HW acceleration
|
||||
|
||||
This change is to rework the bridge APIs based on the feedback from the
|
||||
chromium community
|
||||
|
||||
Change-Id: I92a65f1eb26c6700d871f9deb40bccf302cf18eb
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
---
|
||||
include/linux/if_bridge.h | 8 ++++++
|
||||
net/bridge/br_fdb.c | 38 ++++++++++++++++++++++++++++
|
||||
net/bridge/br_if.c | 52 +++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 98 insertions(+)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -71,6 +71,14 @@ void brioctl_set(int (*hook)(struct net
|
||||
void __user *uarg));
|
||||
int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
|
||||
struct ifreq *ifr, void __user *uarg);
|
||||
+extern struct net_device *br_port_dev_get(struct net_device *dev,
|
||||
+ unsigned char *addr);
|
||||
+extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr);
|
||||
+extern void br_dev_update_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *nlstats);
|
||||
+extern struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||
+ const char *addr,
|
||||
+ __u16 vid);
|
||||
|
||||
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
|
||||
int br_multicast_list_adjacent(struct net_device *dev,
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -914,6 +914,44 @@ void br_fdb_update(struct net_bridge *br
|
||||
}
|
||||
}
|
||||
|
||||
+/* Refresh FDB entries for bridge packets being forwarded by offload engines */
|
||||
+void br_refresh_fdb_entry(struct net_device *dev, const char *addr)
|
||||
+{
|
||||
+ struct net_bridge_port *p = br_port_get_rcu(dev);
|
||||
+
|
||||
+ if (!p || p->state == BR_STATE_DISABLED)
|
||||
+ return;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(addr)) {
|
||||
+ pr_info("bridge: Attempt to refresh with invalid ether address %pM\n",
|
||||
+ addr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ br_fdb_update(p->br, p, addr, 0, true);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_refresh_fdb_entry);
|
||||
+
|
||||
+/* Look up the MAC address in the device's bridge fdb table */
|
||||
+struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||
+ const char *addr, __u16 vid)
|
||||
+{
|
||||
+ struct net_bridge_port *p = br_port_get_rcu(dev);
|
||||
+ struct net_bridge_fdb_entry *fdb;
|
||||
+
|
||||
+ if (!p || p->state == BR_STATE_DISABLED)
|
||||
+ return NULL;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ fdb = fdb_find_rcu(&p->br->fdb_hash_tbl, addr, vid);
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return fdb;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_has_entry);
|
||||
+
|
||||
/* Dump information about entries, in response to GETNEIGH */
|
||||
int br_fdb_dump(struct sk_buff *skb,
|
||||
struct netlink_callback *cb,
|
||||
--- a/net/bridge/br_if.c
|
||||
+++ b/net/bridge/br_if.c
|
||||
@@ -775,3 +775,59 @@ bool br_port_flag_is_set(const struct ne
|
||||
return p->flags & flag;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(br_port_flag_is_set);
|
||||
+
|
||||
+/* br_port_dev_get()
|
||||
+ * Using the given addr, identify the port to which it is reachable,
|
||||
+ * returing a reference to the net device associated with that port.
|
||||
+ *
|
||||
+ * NOTE: Return NULL if given dev is not a bridge or the mac has no
|
||||
+ * associated port.
|
||||
+ */
|
||||
+struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr)
|
||||
+{
|
||||
+ struct net_bridge_fdb_entry *fdbe;
|
||||
+ struct net_bridge *br;
|
||||
+ struct net_device *netdev = NULL;
|
||||
+
|
||||
+ /* Is this a bridge? */
|
||||
+ if (!(dev->priv_flags & IFF_EBRIDGE))
|
||||
+ return NULL;
|
||||
+
|
||||
+ br = netdev_priv(dev);
|
||||
+
|
||||
+ /* Lookup the fdb entry and get reference to the port dev */
|
||||
+ rcu_read_lock();
|
||||
+ fdbe = br_fdb_find_rcu(br, addr, 0);
|
||||
+ if (fdbe && fdbe->dst) {
|
||||
+ netdev = fdbe->dst->dev; /* port device */
|
||||
+ dev_hold(netdev);
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+ return netdev;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_port_dev_get);
|
||||
+
|
||||
+/* 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(dev->tstats);
|
||||
+
|
||||
+ local_bh_disable();
|
||||
+ u64_stats_update_begin(&stats->syncp);
|
||||
+ u64_stats_add(&stats->rx_packets, nlstats->rx_packets);
|
||||
+ u64_stats_add(&stats->rx_bytes, nlstats->rx_bytes);
|
||||
+ u64_stats_add(&stats->tx_packets, nlstats->tx_packets);
|
||||
+ u64_stats_add(&stats->tx_bytes, nlstats->tx_bytes);
|
||||
+ u64_stats_update_end(&stats->syncp);
|
||||
+ local_bh_enable();
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_dev_update_stats);
|
||||
@@ -0,0 +1,99 @@
|
||||
From ae56f1dceb55a3e8e5fadf9bc109270436e3d8fa Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
Date: Thu, 18 May 2023 21:11:09 -0700
|
||||
Subject: [PATCH 220/281] net: bridge: Added bridge fdb update notify chain
|
||||
|
||||
Registered modules are notified based on two events:
|
||||
1. Dst port changes for any existing bridge fdb entry
|
||||
2. Bridge fdb entry ages out/deleted
|
||||
|
||||
Change-Id: Iaba8fba6859bcc8e638df4f2e9900c131b1a6d34
|
||||
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
|
||||
net: bridge : delete fdb entry before callbacks
|
||||
|
||||
Ageing timer expires and deletes corresponding fdb entry. Registered
|
||||
callbacks for br_fdb_update_notifier chains are called one by one.
|
||||
Since callback invocation is before the deletion of fdb entry,
|
||||
it may lead to race condition. Fix is to reorder it.
|
||||
|
||||
Change-Id: Idefce6d879bfa6104cadc495aa61d164db214c97
|
||||
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
---
|
||||
include/linux/if_bridge.h | 2 ++
|
||||
net/bridge/br_fdb.c | 28 ++++++++++++++++++++++++++--
|
||||
2 files changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -79,6 +79,8 @@ extern void br_dev_update_stats(struct n
|
||||
extern struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||
const char *addr,
|
||||
__u16 vid);
|
||||
+extern void br_fdb_update_register_notify(struct notifier_block *nb);
|
||||
+extern void br_fdb_update_unregister_notify(struct notifier_block *nb);
|
||||
|
||||
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
|
||||
int br_multicast_list_adjacent(struct net_device *dev,
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -519,6 +519,20 @@ out:
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
|
||||
+ATOMIC_NOTIFIER_HEAD(br_fdb_update_notifier_list);
|
||||
+
|
||||
+void br_fdb_update_register_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_register(&br_fdb_update_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_update_register_notify);
|
||||
+
|
||||
+void br_fdb_update_unregister_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_unregister(&br_fdb_update_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_update_unregister_notify);
|
||||
+
|
||||
void br_fdb_cleanup(struct work_struct *work)
|
||||
{
|
||||
struct net_bridge *br = container_of(work, struct net_bridge,
|
||||
@@ -527,6 +541,8 @@ void br_fdb_cleanup(struct work_struct *
|
||||
unsigned long delay = hold_time(br);
|
||||
unsigned long work_delay = delay;
|
||||
unsigned long now = jiffies;
|
||||
+ u8 mac_addr[6];
|
||||
+
|
||||
|
||||
/* this part is tricky, in order to avoid blocking learning and
|
||||
* consequently forwarding, we rely on rcu to delete objects with
|
||||
@@ -553,8 +569,12 @@ void br_fdb_cleanup(struct work_struct *
|
||||
work_delay = min(work_delay, this_timer - now);
|
||||
} else {
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
- if (!hlist_unhashed(&f->fdb_node))
|
||||
- fdb_delete(br, f, true);
|
||||
+ if (!hlist_unhashed(&f->fdb_node)) {
|
||||
+ ether_addr_copy(mac_addr, f->key.addr.addr);
|
||||
+ fdb_delete(br, f, true);
|
||||
+ atomic_notifier_call_chain(&br_fdb_update_notifier_list, 0,
|
||||
+ (void *)mac_addr);
|
||||
+ }
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
}
|
||||
@@ -886,6 +906,11 @@ void br_fdb_update(struct net_bridge *br
|
||||
&fdb->flags)))
|
||||
clear_bit(BR_FDB_ADDED_BY_EXT_LEARN,
|
||||
&fdb->flags);
|
||||
+
|
||||
+ atomic_notifier_call_chain(
|
||||
+ &br_fdb_update_notifier_list,
|
||||
+ 0, (void *)addr);
|
||||
+
|
||||
/* Clear locked flag when roaming to an
|
||||
* unlocked port.
|
||||
*/
|
||||
@@ -0,0 +1,112 @@
|
||||
From 449a86c59f4c7c0c58314755b9b638145e8a8d5a Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Wed, 11 Mar 2020 11:20:40 -0700
|
||||
Subject: [PATCH 221/281] Updated the br_port_dev_get function to take an skb
|
||||
|
||||
- If the skb is non-NULL, call the br_port_dev_get_hook (if it exists),
|
||||
to try and fetch the port.
|
||||
- If there is no skb or no hook, or the hook returns NULL, lookup in FDB
|
||||
|
||||
Change-Id: I60df83dfa7a07b39cd30833cba0d4397859711f4
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/if_bridge.h | 9 ++++++++-
|
||||
net/bridge/br_if.c | 38 ++++++++++++++++++++++++++++++++++----
|
||||
2 files changed, 42 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -72,7 +72,8 @@ void brioctl_set(int (*hook)(struct net
|
||||
int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
|
||||
struct ifreq *ifr, void __user *uarg);
|
||||
extern struct net_device *br_port_dev_get(struct net_device *dev,
|
||||
- unsigned char *addr);
|
||||
+ unsigned char *addr,
|
||||
+ struct sk_buff *skb);
|
||||
extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr);
|
||||
extern void br_dev_update_stats(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *nlstats);
|
||||
@@ -223,4 +224,10 @@ static inline clock_t br_get_ageing_time
|
||||
}
|
||||
#endif
|
||||
|
||||
+typedef struct net_bridge_port *br_port_dev_get_hook_t(struct net_device *dev,
|
||||
+ struct sk_buff *skb);
|
||||
+extern br_port_dev_get_hook_t __rcu *br_port_dev_get_hook;
|
||||
+
|
||||
+typedef void (br_notify_hook_t)(int group, int event, const void *ptr);
|
||||
+extern br_notify_hook_t __rcu *br_notify_hook;
|
||||
#endif
|
||||
--- a/net/bridge/br_if.c
|
||||
+++ b/net/bridge/br_if.c
|
||||
@@ -26,6 +26,10 @@
|
||||
|
||||
#include "br_private.h"
|
||||
|
||||
+/* Hook for external forwarding logic */
|
||||
+br_port_dev_get_hook_t __rcu *br_port_dev_get_hook __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(br_port_dev_get_hook);
|
||||
+
|
||||
/*
|
||||
* Determine initial path cost based on speed.
|
||||
* using recommendations from 802.1d standard
|
||||
@@ -777,13 +781,17 @@ bool br_port_flag_is_set(const struct ne
|
||||
EXPORT_SYMBOL_GPL(br_port_flag_is_set);
|
||||
|
||||
/* br_port_dev_get()
|
||||
- * Using the given addr, identify the port to which it is reachable,
|
||||
- * returing a reference to the net device associated with that port.
|
||||
+ * If a skb is provided, and the br_port_dev_get_hook_t hook exists,
|
||||
+ * use that to try and determine the egress port for that skb.
|
||||
+ * If not, or no egress port could be determined, use the given addr
|
||||
+ * to identify the port to which it is reachable,
|
||||
+ * returing a reference to the net device associated with that port.
|
||||
*
|
||||
* NOTE: Return NULL if given dev is not a bridge or the mac has no
|
||||
* associated port.
|
||||
*/
|
||||
-struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr)
|
||||
+struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr,
|
||||
+ struct sk_buff *skb)
|
||||
{
|
||||
struct net_bridge_fdb_entry *fdbe;
|
||||
struct net_bridge *br;
|
||||
@@ -793,15 +801,37 @@ struct net_device *br_port_dev_get(struc
|
||||
if (!(dev->priv_flags & IFF_EBRIDGE))
|
||||
return NULL;
|
||||
|
||||
+ rcu_read_lock();
|
||||
+
|
||||
+ /* If the hook exists and the skb isn't NULL, try and get the port */
|
||||
+ if (skb) {
|
||||
+ br_port_dev_get_hook_t *port_dev_get_hook;
|
||||
+
|
||||
+ port_dev_get_hook = rcu_dereference(br_port_dev_get_hook);
|
||||
+ if (port_dev_get_hook) {
|
||||
+ struct net_bridge_port *pdst =
|
||||
+ __br_get(port_dev_get_hook, NULL, dev, skb);
|
||||
+ if (pdst) {
|
||||
+ dev_hold(pdst->dev);
|
||||
+ netdev = pdst->dev;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Either there is no hook, or can't
|
||||
+ * determine the port to use - fall back to using FDB
|
||||
+ */
|
||||
+
|
||||
br = netdev_priv(dev);
|
||||
|
||||
/* Lookup the fdb entry and get reference to the port dev */
|
||||
- rcu_read_lock();
|
||||
fdbe = br_fdb_find_rcu(br, addr, 0);
|
||||
if (fdbe && fdbe->dst) {
|
||||
netdev = fdbe->dst->dev; /* port device */
|
||||
dev_hold(netdev);
|
||||
}
|
||||
+out:
|
||||
rcu_read_unlock();
|
||||
return netdev;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
From 14b84b541426e1237e33aced57d08a25d1885098 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Tue, 27 Jan 2015 18:06:30 +0000
|
||||
Subject: [PATCH 222/281] vlan: Add vlan stats update function
|
||||
|
||||
Change-Id: Ib1165b37f29d48e5dbcee2c709b2f873dfb3e34d
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/if_vlan.h | 9 +++++++++
|
||||
net/8021q/vlan_core.c | 20 ++++++++++++++++++++
|
||||
2 files changed, 29 insertions(+)
|
||||
|
||||
--- a/include/linux/if_vlan.h
|
||||
+++ b/include/linux/if_vlan.h
|
||||
@@ -143,6 +143,9 @@ extern struct net_device *__vlan_find_de
|
||||
extern int vlan_for_each(struct net_device *dev,
|
||||
int (*action)(struct net_device *dev, int vid,
|
||||
void *arg), void *arg);
|
||||
+extern void __vlan_dev_update_accel_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *stats);
|
||||
+
|
||||
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
|
||||
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
|
||||
extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
|
||||
@@ -236,6 +239,12 @@ extern void vlan_vids_del_by_dev(struct
|
||||
extern bool vlan_uses_dev(const struct net_device *dev);
|
||||
|
||||
#else
|
||||
+static inline void __vlan_dev_update_accel_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *stats)
|
||||
+{
|
||||
+
|
||||
+}
|
||||
+
|
||||
static inline struct net_device *
|
||||
__vlan_find_dev_deep_rcu(struct net_device *real_dev,
|
||||
__be16 vlan_proto, u16 vlan_id)
|
||||
--- a/net/8021q/vlan_core.c
|
||||
+++ b/net/8021q/vlan_core.c
|
||||
@@ -72,6 +72,26 @@ bool vlan_do_receive(struct sk_buff **sk
|
||||
return true;
|
||||
}
|
||||
|
||||
+/* Update the VLAN device with statistics from network offload engines */
|
||||
+void __vlan_dev_update_accel_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *nlstats)
|
||||
+{
|
||||
+ struct vlan_pcpu_stats *stats;
|
||||
+
|
||||
+ if (!is_vlan_dev(dev))
|
||||
+ return;
|
||||
+
|
||||
+ stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats);
|
||||
+
|
||||
+ u64_stats_update_begin(&stats->syncp);
|
||||
+ u64_stats_add(&stats->rx_packets, nlstats->rx_packets);
|
||||
+ u64_stats_add(&stats->rx_bytes, nlstats->rx_bytes);
|
||||
+ u64_stats_add(&stats->tx_packets, nlstats->tx_packets);
|
||||
+ u64_stats_add(&stats->tx_bytes, nlstats->tx_bytes);
|
||||
+ u64_stats_update_end(&stats->syncp);
|
||||
+}
|
||||
+EXPORT_SYMBOL(__vlan_dev_update_accel_stats);
|
||||
+
|
||||
/* Must be invoked with rcu_read_lock. */
|
||||
struct net_device *__vlan_find_dev_deep_rcu(struct net_device *dev,
|
||||
__be16 vlan_proto, u16 vlan_id)
|
||||
@@ -0,0 +1,123 @@
|
||||
From 84fa3efb7d8eeb1c3f2daf9a3034e2794b3294f9 Mon Sep 17 00:00:00 2001
|
||||
From: Zhi Chen <zhichen@codeaurora.org>
|
||||
Date: Mon, 13 Apr 2015 16:39:06 -0700
|
||||
Subject: [PATCH 223/281] linux: bridge: add patch for IGMP/MLD snooping
|
||||
|
||||
Kernel patch for the IGMP/MLD snooping module, which is a replacement
|
||||
and enhancement of Linux bridge multicast snooping. With the IGMP/MLD
|
||||
snooping module, we can support IGMPv3/MLDv2 on Linux bridge.
|
||||
Furthermore, with additional plugins, we can support switch port-based
|
||||
snooping and WiFi conversion from multicast to unicast.
|
||||
This patch exported a couple of bridge APIs and added two packet hooks
|
||||
on the input/output path.
|
||||
|
||||
Change-Id: I3507f2b793155856b4dac8ad5937a9fc6d28551d
|
||||
Signed-off-by: Zhi Chen <zhichen@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/if_bridge.h | 6 ++++++
|
||||
net/bridge/br_device.c | 5 +++++
|
||||
net/bridge/br_input.c | 12 +++++++++++-
|
||||
net/bridge/br_private.h | 5 +++++
|
||||
4 files changed, 27 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -66,11 +66,13 @@ struct br_ip_list {
|
||||
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
|
||||
|
||||
struct net_bridge;
|
||||
+struct net_bridge_port;
|
||||
void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
|
||||
unsigned int cmd, struct ifreq *ifr,
|
||||
void __user *uarg));
|
||||
int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
|
||||
struct ifreq *ifr, void __user *uarg);
|
||||
+
|
||||
extern struct net_device *br_port_dev_get(struct net_device *dev,
|
||||
unsigned char *addr,
|
||||
struct sk_buff *skb);
|
||||
@@ -230,4 +232,8 @@ extern br_port_dev_get_hook_t __rcu *br_
|
||||
|
||||
typedef void (br_notify_hook_t)(int group, int event, const void *ptr);
|
||||
extern br_notify_hook_t __rcu *br_notify_hook;
|
||||
+typedef int (br_multicast_handle_hook_t)(const struct net_bridge_port *src,
|
||||
+ struct sk_buff *skb);
|
||||
+extern br_multicast_handle_hook_t __rcu *br_multicast_handle_hook;
|
||||
+
|
||||
#endif
|
||||
--- a/net/bridge/br_device.c
|
||||
+++ b/net/bridge/br_device.c
|
||||
@@ -89,6 +89,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *
|
||||
if (is_broadcast_ether_addr(dest)) {
|
||||
br_flood(br, skb, BR_PKT_BROADCAST, false, true, vid);
|
||||
} else if (is_multicast_ether_addr(dest)) {
|
||||
+ br_multicast_handle_hook_t *multicast_handle_hook =
|
||||
+ rcu_dereference(br_multicast_handle_hook);
|
||||
+ if (!__br_get(multicast_handle_hook, true, NULL, skb))
|
||||
+ goto out;
|
||||
+
|
||||
if (unlikely(netpoll_tx_running(dev))) {
|
||||
br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
|
||||
goto out;
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -30,7 +30,11 @@ br_netif_receive_skb(struct net *net, st
|
||||
return netif_receive_skb(skb);
|
||||
}
|
||||
|
||||
-static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
|
||||
+/* Hook for external Multicast handler */
|
||||
+br_multicast_handle_hook_t __rcu *br_multicast_handle_hook __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(br_multicast_handle_hook);
|
||||
+
|
||||
+int br_pass_frame_up(struct sk_buff *skb, bool promisc)
|
||||
{
|
||||
struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
|
||||
struct net_bridge *br = netdev_priv(brdev);
|
||||
@@ -71,6 +75,7 @@ static int br_pass_frame_up(struct sk_bu
|
||||
dev_net(indev), NULL, skb, indev, NULL,
|
||||
br_netif_receive_skb);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(br_pass_frame_up);
|
||||
|
||||
/* note: already called with rcu_read_lock */
|
||||
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
@@ -85,6 +90,7 @@ int br_handle_frame_finish(struct net *n
|
||||
struct net_bridge_vlan *vlan;
|
||||
struct net_bridge *br;
|
||||
bool promisc;
|
||||
+ br_multicast_handle_hook_t *multicast_handle_hook;
|
||||
u16 vid = 0;
|
||||
u8 state;
|
||||
|
||||
@@ -182,6 +188,10 @@ int br_handle_frame_finish(struct net *n
|
||||
|
||||
switch (pkt_type) {
|
||||
case BR_PKT_MULTICAST:
|
||||
+ multicast_handle_hook = rcu_dereference(br_multicast_handle_hook);
|
||||
+ if (!__br_get(multicast_handle_hook, true, p, skb))
|
||||
+ goto out;
|
||||
+
|
||||
mdst = br_mdb_get(brmctx, skb, vid);
|
||||
if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
|
||||
br_multicast_querier_exists(brmctx, eth_hdr(skb), mdst)) {
|
||||
--- a/net/bridge/br_private.h
|
||||
+++ b/net/bridge/br_private.h
|
||||
@@ -907,6 +907,7 @@ void br_manage_promisc(struct net_bridge
|
||||
int nbp_backup_change(struct net_bridge_port *p, struct net_device *backup_dev);
|
||||
|
||||
/* br_input.c */
|
||||
+int br_pass_frame_up(struct sk_buff *skb, bool promisc);
|
||||
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb);
|
||||
rx_handler_func_t *br_get_rx_handler(const struct net_device *dev);
|
||||
|
||||
@@ -2268,4 +2269,8 @@ void br_do_suppress_nd(struct sk_buff *s
|
||||
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
|
||||
struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
|
||||
bool br_is_neigh_suppress_enabled(const struct net_bridge_port *p, u16 vid);
|
||||
+
|
||||
+#define __br_get(__hook, __default, __args ...) \
|
||||
+ (__hook ? (__hook(__args)) : (__default))
|
||||
+
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
From c38b43a2a98eaf2dd3401998e982716e98339907 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Tue, 27 Jan 2015 11:10:26 -0800
|
||||
Subject: [PATCH 224/281] ipv6: Export ndisc_send_ns() function for public use.
|
||||
|
||||
This API is needed to implement a connection
|
||||
manager for hardware accelaration.
|
||||
|
||||
Change-Id: Idcf5fa1d3d3151fa2a5e0c48c6b6cdd10fc335bf
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
net/ipv6/ndisc.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/net/ipv6/ndisc.c
|
||||
+++ b/net/ipv6/ndisc.c
|
||||
@@ -670,6 +670,7 @@ void ndisc_send_ns(struct net_device *de
|
||||
if (skb)
|
||||
ndisc_send_skb(skb, daddr, saddr);
|
||||
}
|
||||
+EXPORT_SYMBOL(ndisc_send_ns);
|
||||
|
||||
void ndisc_send_rs(struct net_device *dev, const struct in6_addr *saddr,
|
||||
const struct in6_addr *daddr)
|
||||
@@ -0,0 +1,150 @@
|
||||
From 776142dbbc2a3da1d47d1042822f72ba3127417b Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Wed, 10 Feb 2016 15:38:12 -0800
|
||||
Subject: [PATCH 225/281] net: ipv4/ipv6: Added route table update notify chain
|
||||
|
||||
Registered modules are notified for the changes in the
|
||||
route table.
|
||||
|
||||
NOTE: This patch is originally suggested by "Jozsef Kadlecsik"
|
||||
in the following email chain but never merged to any of the
|
||||
kernel versions.
|
||||
http://www.spinics.net/lists/netfilter-devel/msg24239.html
|
||||
|
||||
Cc: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
Patch-mainline: netfilter-devel@vger.kernel.org
|
||||
|
||||
Change-Id: I402710474be0978867dfbbbb8d1a7f8c8f3dab06
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/net/ip6_route.h | 3 +++
|
||||
include/net/route.h | 3 +++
|
||||
net/ipv4/fib_trie.c | 19 +++++++++++++++++++
|
||||
net/ipv6/route.c | 22 +++++++++++++++++++++-
|
||||
4 files changed, 46 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/net/ip6_route.h
|
||||
+++ b/include/net/ip6_route.h
|
||||
@@ -215,6 +215,9 @@ void rt6_multipath_rebalance(struct fib6
|
||||
void rt6_uncached_list_add(struct rt6_info *rt);
|
||||
void rt6_uncached_list_del(struct rt6_info *rt);
|
||||
|
||||
+int rt6_register_notifier(struct notifier_block *nb);
|
||||
+int rt6_unregister_notifier(struct notifier_block *nb);
|
||||
+
|
||||
static inline const struct rt6_info *skb_rt6_info(const struct sk_buff *skb)
|
||||
{
|
||||
const struct dst_entry *dst = skb_dst(skb);
|
||||
--- a/include/net/route.h
|
||||
+++ b/include/net/route.h
|
||||
@@ -237,6 +237,9 @@ struct rtable *rt_dst_alloc(struct net_d
|
||||
unsigned int flags, u16 type, bool noxfrm);
|
||||
struct rtable *rt_dst_clone(struct net_device *dev, struct rtable *rt);
|
||||
|
||||
+int ip_rt_register_notifier(struct notifier_block *nb);
|
||||
+int ip_rt_unregister_notifier(struct notifier_block *nb);
|
||||
+
|
||||
struct in_ifaddr;
|
||||
void fib_add_ifaddr(struct in_ifaddr *);
|
||||
void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
|
||||
--- a/net/ipv4/fib_trie.c
|
||||
+++ b/net/ipv4/fib_trie.c
|
||||
@@ -1211,6 +1211,9 @@ static bool fib_valid_key_len(u32 key, u
|
||||
static void fib_remove_alias(struct trie *t, struct key_vector *tp,
|
||||
struct key_vector *l, struct fib_alias *old);
|
||||
|
||||
+/* Define route change notification chain. */
|
||||
+static BLOCKING_NOTIFIER_HEAD(iproute_chain);
|
||||
+
|
||||
/* Caller must hold RTNL. */
|
||||
int fib_table_insert(struct net *net, struct fib_table *tb,
|
||||
struct fib_config *cfg, struct netlink_ext_ack *extack)
|
||||
@@ -1404,6 +1407,8 @@ int fib_table_insert(struct net *net, st
|
||||
rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, new_fa->tb_id,
|
||||
&cfg->fc_nlinfo, nlflags);
|
||||
succeeded:
|
||||
+ blocking_notifier_call_chain(&iproute_chain,
|
||||
+ RTM_NEWROUTE, fi);
|
||||
return 0;
|
||||
|
||||
out_remove_new_fa:
|
||||
@@ -1776,6 +1781,8 @@ int fib_table_delete(struct net *net, st
|
||||
if (fa_to_delete->fa_state & FA_S_ACCESSED)
|
||||
rt_cache_flush(cfg->fc_nlinfo.nl_net);
|
||||
|
||||
+ blocking_notifier_call_chain(&iproute_chain,
|
||||
+ RTM_DELROUTE, fa_to_delete->fa_info);
|
||||
fib_release_info(fa_to_delete->fa_info);
|
||||
alias_free_mem_rcu(fa_to_delete);
|
||||
return 0;
|
||||
@@ -2408,6 +2415,18 @@ void __init fib_trie_init(void)
|
||||
0, SLAB_PANIC | SLAB_ACCOUNT, NULL);
|
||||
}
|
||||
|
||||
+int ip_rt_register_notifier(struct notifier_block *nb)
|
||||
+{
|
||||
+ return blocking_notifier_chain_register(&iproute_chain, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip_rt_register_notifier);
|
||||
+
|
||||
+int ip_rt_unregister_notifier(struct notifier_block *nb)
|
||||
+{
|
||||
+ return blocking_notifier_chain_unregister(&iproute_chain, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip_rt_unregister_notifier);
|
||||
+
|
||||
struct fib_table *fib_trie_table(u32 id, struct fib_table *alias)
|
||||
{
|
||||
struct fib_table *tb;
|
||||
--- a/net/ipv6/route.c
|
||||
+++ b/net/ipv6/route.c
|
||||
@@ -198,6 +198,9 @@ static void rt6_uncached_list_flush_dev(
|
||||
}
|
||||
}
|
||||
|
||||
+/* Define route change notification chain. */
|
||||
+ATOMIC_NOTIFIER_HEAD(ip6route_chain);
|
||||
+
|
||||
static inline const void *choose_neigh_daddr(const struct in6_addr *p,
|
||||
struct sk_buff *skb,
|
||||
const void *daddr)
|
||||
@@ -3873,6 +3876,9 @@ int ip6_route_add(struct fib6_config *cf
|
||||
return PTR_ERR(rt);
|
||||
|
||||
err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack);
|
||||
+ if (!err)
|
||||
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||
+ RTM_NEWROUTE, rt);
|
||||
fib6_info_release(rt);
|
||||
|
||||
return err;
|
||||
@@ -3893,7 +3899,9 @@ static int __ip6_del_rt(struct fib6_info
|
||||
spin_lock_bh(&table->tb6_lock);
|
||||
err = fib6_del(rt, info);
|
||||
spin_unlock_bh(&table->tb6_lock);
|
||||
-
|
||||
+ if (!err)
|
||||
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||
+ RTM_DELROUTE, rt);
|
||||
out:
|
||||
fib6_info_release(rt);
|
||||
return err;
|
||||
@@ -6356,6 +6364,18 @@ static int ip6_route_dev_notify(struct n
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
+int rt6_register_notifier(struct notifier_block *nb)
|
||||
+{
|
||||
+ return atomic_notifier_chain_register(&ip6route_chain, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL(rt6_register_notifier);
|
||||
+
|
||||
+int rt6_unregister_notifier(struct notifier_block *nb)
|
||||
+{
|
||||
+ return atomic_notifier_chain_unregister(&ip6route_chain, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL(rt6_unregister_notifier);
|
||||
+
|
||||
/*
|
||||
* /proc
|
||||
*/
|
||||
@@ -0,0 +1,78 @@
|
||||
From bbe88f4bc0087f25eb2608f9112d480ce92b33a5 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Wed, 11 Mar 2020 11:58:55 -0700
|
||||
Subject: [PATCH 226/281] net: patch linux kernel to support shortcut-fe
|
||||
|
||||
1, add a new flag 'fast_forwarded' in skb structure.
|
||||
2, put a hook in '__netif_receive_skb_core' to
|
||||
deliver packet to shortcut-fe.
|
||||
|
||||
Change-Id: Icaa7c172a06df1c3bc89ff89814d1136772fe217
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/skbuff.h | 2 ++
|
||||
net/core/dev.c | 21 +++++++++++++++++++--
|
||||
2 files changed, 21 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/include/linux/skbuff.h
|
||||
+++ b/include/linux/skbuff.h
|
||||
@@ -984,6 +984,8 @@ struct sk_buff {
|
||||
#if IS_ENABLED(CONFIG_IP_SCTP)
|
||||
__u8 csum_not_inet:1;
|
||||
#endif
|
||||
+ __u8 fast_forwarded:1;
|
||||
+ /* 1 or 3 bit hole */
|
||||
|
||||
#if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS)
|
||||
__u16 tc_index; /* traffic control index */
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -3594,8 +3594,13 @@ static int xmit_one(struct sk_buff *skb,
|
||||
unsigned int len;
|
||||
int rc;
|
||||
|
||||
- if (dev_nit_active(dev))
|
||||
- dev_queue_xmit_nit(skb, dev);
|
||||
+ /* 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 (unlikely(!skb->fast_forwarded)) {
|
||||
+ if (dev_nit_active(dev))
|
||||
+ dev_queue_xmit_nit(skb, dev);
|
||||
+ }
|
||||
|
||||
#ifdef CONFIG_ETHERNET_PACKET_MANGLE
|
||||
if (dev->eth_mangle_tx && !(skb = dev->eth_mangle_tx(dev, skb)))
|
||||
@@ -5365,6 +5370,9 @@ void netdev_rx_handler_unregister(struct
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
|
||||
|
||||
+int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
|
||||
+
|
||||
/*
|
||||
* Limit the use of PFMEMALLOC reserves to those protocols that implement
|
||||
* the special handling of PFMEMALLOC skbs.
|
||||
@@ -5412,6 +5420,7 @@ static int __netif_receive_skb_core(stru
|
||||
bool deliver_exact = false;
|
||||
int ret = NET_RX_DROP;
|
||||
__be16 type;
|
||||
+ int (*fast_recv)(struct sk_buff *skb);
|
||||
|
||||
net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb);
|
||||
|
||||
@@ -5450,6 +5459,14 @@ another_round:
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ fast_recv = rcu_dereference(athrs_fast_nat_recv);
|
||||
+ if (fast_recv) {
|
||||
+ if (fast_recv(skb)) {
|
||||
+ ret = NET_RX_SUCCESS;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (skb_skip_tc_classify(skb))
|
||||
goto skip_classify;
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
From 781701738687f5cc13ae949410b162a2cdda817f Mon Sep 17 00:00:00 2001
|
||||
From: Zhi Chen <zhichen@codeaurora.org>
|
||||
Date: Thu, 27 Aug 2015 16:37:09 -0700
|
||||
Subject: [PATCH 227/281] bridge: add fdb events in linux bridge
|
||||
|
||||
Notify fdb changing events to those modules which are interested in
|
||||
hosts joining/leaving or bridge port changing. This is required by
|
||||
RFS feature.
|
||||
|
||||
Change-Id: I7b592ba09109e1785a5834b56987a19bc35886fe
|
||||
Signed-off-by: Zhi Chen <zhichen@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/if_bridge.h | 11 +++++++++++
|
||||
net/bridge/br_fdb.c | 31 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 42 insertions(+)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -236,4 +236,15 @@ typedef int (br_multicast_handle_hook_t)
|
||||
struct sk_buff *skb);
|
||||
extern br_multicast_handle_hook_t __rcu *br_multicast_handle_hook;
|
||||
|
||||
+#define BR_FDB_EVENT_ADD 0x01
|
||||
+#define BR_FDB_EVENT_DEL 0x02
|
||||
+
|
||||
+struct br_fdb_event {
|
||||
+ struct net_device *dev;
|
||||
+ unsigned char addr[6];
|
||||
+ unsigned char is_local;
|
||||
+};
|
||||
+
|
||||
+extern void br_fdb_register_notify(struct notifier_block *nb);
|
||||
+extern void br_fdb_unregister_notify(struct notifier_block *nb);
|
||||
#endif
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -33,6 +33,20 @@ static const struct rhashtable_params br
|
||||
|
||||
static struct kmem_cache *br_fdb_cache __read_mostly;
|
||||
|
||||
+ATOMIC_NOTIFIER_HEAD(br_fdb_notifier_list);
|
||||
+
|
||||
+void br_fdb_register_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_register(&br_fdb_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_register_notify);
|
||||
+
|
||||
+void br_fdb_unregister_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_unregister(&br_fdb_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_unregister_notify);
|
||||
+
|
||||
int __init br_fdb_init(void)
|
||||
{
|
||||
br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
|
||||
@@ -195,6 +209,23 @@ static void fdb_notify(struct net_bridge
|
||||
if (swdev_notify)
|
||||
br_switchdev_fdb_notify(br, fdb, type);
|
||||
|
||||
+ if (fdb->dst) {
|
||||
+ int event;
|
||||
+ struct br_fdb_event fdb_event;
|
||||
+
|
||||
+ if (type == RTM_NEWNEIGH)
|
||||
+ event = BR_FDB_EVENT_ADD;
|
||||
+ else
|
||||
+ event = BR_FDB_EVENT_DEL;
|
||||
+
|
||||
+ fdb_event.dev = fdb->dst->dev;
|
||||
+ ether_addr_copy(fdb_event.addr, fdb->key.addr.addr);
|
||||
+ fdb_event.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
|
||||
+ atomic_notifier_call_chain(&br_fdb_notifier_list,
|
||||
+ event,
|
||||
+ (void *)&fdb_event);
|
||||
+ }
|
||||
+
|
||||
skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
goto errout;
|
||||
@@ -0,0 +1,44 @@
|
||||
From 8632dd2d78d1935c3eab058017eab4f2d1702ecc Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Fri, 24 Apr 2020 10:58:42 -0700
|
||||
Subject: [PATCH 228/281] inet: vlan: Added an API to return next VLAN device
|
||||
|
||||
The new API returns the next dev when a VLAN dev passed
|
||||
in parameter i.e.
|
||||
eth0.10.20 -> eth0.10 -> eth0 The new API returns eth0.10
|
||||
when eth0.10.20 is passed as a parameter.
|
||||
|
||||
Change-Id: I743beb0672e8fd0d6562eec8ec88b1e36eec2973
|
||||
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/if_vlan.h | 1 +
|
||||
net/8021q/vlan_core.c | 7 +++++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
--- a/include/linux/if_vlan.h
|
||||
+++ b/include/linux/if_vlan.h
|
||||
@@ -147,6 +147,7 @@ extern void __vlan_dev_update_accel_stat
|
||||
struct rtnl_link_stats64 *stats);
|
||||
|
||||
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
|
||||
+extern struct net_device *vlan_dev_next_dev(const struct net_device *dev);
|
||||
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
|
||||
extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
|
||||
|
||||
--- a/net/8021q/vlan_core.c
|
||||
+++ b/net/8021q/vlan_core.c
|
||||
@@ -130,6 +130,13 @@ struct net_device *vlan_dev_real_dev(con
|
||||
}
|
||||
EXPORT_SYMBOL(vlan_dev_real_dev);
|
||||
|
||||
+/* Caller is responsible to hold the reference of the returned device */
|
||||
+struct net_device *vlan_dev_next_dev(const struct net_device *dev)
|
||||
+{
|
||||
+ return vlan_dev_priv(dev)->real_dev;
|
||||
+}
|
||||
+EXPORT_SYMBOL(vlan_dev_next_dev);
|
||||
+
|
||||
u16 vlan_dev_vlan_id(const struct net_device *dev)
|
||||
{
|
||||
return vlan_dev_priv(dev)->vlan_id;
|
||||
@@ -0,0 +1,41 @@
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -2939,6 +2939,8 @@ enum netdev_cmd {
|
||||
NETDEV_OFFLOAD_XSTATS_REPORT_USED,
|
||||
NETDEV_OFFLOAD_XSTATS_REPORT_DELTA,
|
||||
NETDEV_XDP_FEAT_CHANGE,
|
||||
+ NETDEV_BR_JOIN,
|
||||
+ NETDEV_BR_LEAVE,
|
||||
};
|
||||
const char *netdev_cmd_to_name(enum netdev_cmd cmd);
|
||||
|
||||
--- a/net/bridge/br_if.c
|
||||
+++ b/net/bridge/br_if.c
|
||||
@@ -700,6 +700,7 @@ int br_add_if(struct net_bridge *br, str
|
||||
br_set_gso_limits(br);
|
||||
|
||||
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||
+ call_netdevice_notifiers(NETDEV_BR_JOIN, dev);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -736,6 +737,8 @@ int br_del_if(struct net_bridge *br, str
|
||||
if (!p || p->br != br)
|
||||
return -EINVAL;
|
||||
|
||||
+ call_netdevice_notifiers(NETDEV_BR_LEAVE, dev);
|
||||
+
|
||||
/* Since more than one interface can be attached to a bridge,
|
||||
* there still maybe an alternate path for netconsole to use;
|
||||
* therefore there is no reason for a NETDEV_RELEASE event.
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -1699,6 +1699,8 @@ const char *netdev_cmd_to_name(enum netd
|
||||
N(PRE_CHANGEADDR) N(OFFLOAD_XSTATS_ENABLE) N(OFFLOAD_XSTATS_DISABLE)
|
||||
N(OFFLOAD_XSTATS_REPORT_USED) N(OFFLOAD_XSTATS_REPORT_DELTA)
|
||||
N(XDP_FEAT_CHANGE)
|
||||
+ N(BR_JOIN) N(BR_LEAVE)
|
||||
+
|
||||
}
|
||||
#undef N
|
||||
return "UNKNOWN_NETDEV_EVENT";
|
||||
@@ -0,0 +1,215 @@
|
||||
From 86f006a651d5415d046be00c851d15e86abae6bb Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
Date: Thu, 18 May 2023 21:11:39 -0700
|
||||
Subject: [PATCH 230/281] bridge: Port Hy-Fi bridging hooks
|
||||
|
||||
Introduce two new netfilter hooks. The first allows the Hy-Fi bridging
|
||||
logic to indicate a different egress port (thereby overriding the FDB).
|
||||
The other is used for FDB update notifications and port changes.
|
||||
|
||||
Change-Id: I21549968c56e6b60d7d08e19ec4a297b937264bf
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
|
||||
Pass MAC address to Hy-Fi bridge
|
||||
|
||||
- This may be a skb on the forward or reverse direction of the
|
||||
connection
|
||||
- Need to pass the dest address as well as the skb to determine if we
|
||||
need to calculate the forward or reverse hash
|
||||
|
||||
Change-Id: I245855910ac91f73a9e9e6bd3403f01bc662a93a
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
|
||||
Pass serial number to Linux bridge port lookup
|
||||
|
||||
- This allows the same ECM lookup function to be used in interface
|
||||
hierarchy generation and when updating stats (so no difference in
|
||||
lookup even if the priority field changes)
|
||||
- If the priority field changes, will update the H-Active entry and
|
||||
generate a debug log
|
||||
|
||||
Change-Id: I392bbc82fab30c345b14e7927b6b0fa119d19a57
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
---
|
||||
include/linux/if_bridge.h | 15 +++++++++++++--
|
||||
net/bridge/br.c | 4 ++++
|
||||
net/bridge/br_fdb.c | 2 ++
|
||||
net/bridge/br_if.c | 6 ++++--
|
||||
net/bridge/br_input.c | 20 +++++++++++++++++++-
|
||||
net/bridge/br_netlink.c | 2 ++
|
||||
net/bridge/br_private.h | 9 +++++++++
|
||||
7 files changed, 53 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -75,7 +75,8 @@ int br_ioctl_call(struct net *net, struc
|
||||
|
||||
extern struct net_device *br_port_dev_get(struct net_device *dev,
|
||||
unsigned char *addr,
|
||||
- struct sk_buff *skb);
|
||||
+ struct sk_buff *skb,
|
||||
+ unsigned int cookie);
|
||||
extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr);
|
||||
extern void br_dev_update_stats(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *nlstats);
|
||||
@@ -227,7 +228,9 @@ static inline clock_t br_get_ageing_time
|
||||
#endif
|
||||
|
||||
typedef struct net_bridge_port *br_port_dev_get_hook_t(struct net_device *dev,
|
||||
- struct sk_buff *skb);
|
||||
+ struct sk_buff *skb,
|
||||
+ unsigned char *addr,
|
||||
+ unsigned int cookie);
|
||||
extern br_port_dev_get_hook_t __rcu *br_port_dev_get_hook;
|
||||
|
||||
typedef void (br_notify_hook_t)(int group, int event, const void *ptr);
|
||||
@@ -247,4 +250,12 @@ struct br_fdb_event {
|
||||
|
||||
extern void br_fdb_register_notify(struct notifier_block *nb);
|
||||
extern void br_fdb_unregister_notify(struct notifier_block *nb);
|
||||
+
|
||||
+typedef struct net_bridge_port *br_get_dst_hook_t(
|
||||
+ const struct net_bridge_port *src,
|
||||
+ struct sk_buff **skb);
|
||||
+extern br_get_dst_hook_t __rcu *br_get_dst_hook;
|
||||
+
|
||||
+typedef void (br_notify_hook_t)(int group, int event, const void *ptr);
|
||||
+extern br_notify_hook_t __rcu *br_notify_hook;
|
||||
#endif
|
||||
--- a/net/bridge/br.c
|
||||
+++ b/net/bridge/br.c
|
||||
@@ -472,6 +472,10 @@ static void __exit br_deinit(void)
|
||||
br_fdb_fini();
|
||||
}
|
||||
|
||||
+/* Hook for bridge event notifications */
|
||||
+br_notify_hook_t __rcu *br_notify_hook __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(br_notify_hook);
|
||||
+
|
||||
module_init(br_init)
|
||||
module_exit(br_deinit)
|
||||
MODULE_LICENSE("GPL");
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -237,6 +237,8 @@ static void fdb_notify(struct net_bridge
|
||||
kfree_skb(skb);
|
||||
goto errout;
|
||||
}
|
||||
+
|
||||
+ __br_notify(RTNLGRP_NEIGH, type, fdb);
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
|
||||
return;
|
||||
errout:
|
||||
--- a/net/bridge/br_if.c
|
||||
+++ b/net/bridge/br_if.c
|
||||
@@ -794,7 +794,8 @@ EXPORT_SYMBOL_GPL(br_port_flag_is_set);
|
||||
* associated port.
|
||||
*/
|
||||
struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr,
|
||||
- struct sk_buff *skb)
|
||||
+ struct sk_buff *skb,
|
||||
+ unsigned int cookie)
|
||||
{
|
||||
struct net_bridge_fdb_entry *fdbe;
|
||||
struct net_bridge *br;
|
||||
@@ -813,7 +814,8 @@ struct net_device *br_port_dev_get(struc
|
||||
port_dev_get_hook = rcu_dereference(br_port_dev_get_hook);
|
||||
if (port_dev_get_hook) {
|
||||
struct net_bridge_port *pdst =
|
||||
- __br_get(port_dev_get_hook, NULL, dev, skb);
|
||||
+ __br_get(port_dev_get_hook, NULL, dev, skb,
|
||||
+ addr, cookie);
|
||||
if (pdst) {
|
||||
dev_hold(pdst->dev);
|
||||
netdev = pdst->dev;
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -34,6 +34,10 @@ br_netif_receive_skb(struct net *net, st
|
||||
br_multicast_handle_hook_t __rcu *br_multicast_handle_hook __read_mostly;
|
||||
EXPORT_SYMBOL_GPL(br_multicast_handle_hook);
|
||||
|
||||
+/* Hook for external forwarding logic */
|
||||
+br_get_dst_hook_t __rcu *br_get_dst_hook __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(br_get_dst_hook);
|
||||
+
|
||||
int br_pass_frame_up(struct sk_buff *skb, bool promisc)
|
||||
{
|
||||
struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
|
||||
@@ -91,6 +95,8 @@ int br_handle_frame_finish(struct net *n
|
||||
struct net_bridge *br;
|
||||
bool promisc;
|
||||
br_multicast_handle_hook_t *multicast_handle_hook;
|
||||
+ struct net_bridge_port *pdst = NULL;
|
||||
+ br_get_dst_hook_t *get_dst_hook = rcu_dereference(br_get_dst_hook);
|
||||
u16 vid = 0;
|
||||
u8 state;
|
||||
|
||||
@@ -207,7 +213,13 @@ int br_handle_frame_finish(struct net *n
|
||||
}
|
||||
break;
|
||||
case BR_PKT_UNICAST:
|
||||
- dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid);
|
||||
+ pdst = __br_get(get_dst_hook, NULL, p, &skb);
|
||||
+ if (pdst) {
|
||||
+ if (!skb)
|
||||
+ goto out;
|
||||
+ } else {
|
||||
+ dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid);
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -223,12 +235,18 @@ int br_handle_frame_finish(struct net *n
|
||||
dst->used = now;
|
||||
br_forward(dst->dst, skb, local_rcv, false);
|
||||
} else {
|
||||
+ if (pdst) {
|
||||
+ br_forward(pdst, skb, local_rcv, false);
|
||||
+ goto out1;
|
||||
+ }
|
||||
+
|
||||
if (!mcast_hit)
|
||||
br_flood(br, skb, pkt_type, local_rcv, false, vid);
|
||||
else
|
||||
br_multicast_flood(mdst, skb, brmctx, local_rcv, false);
|
||||
}
|
||||
|
||||
+out1:
|
||||
if (local_rcv)
|
||||
return br_pass_frame_up(skb, promisc);
|
||||
|
||||
--- a/net/bridge/br_netlink.c
|
||||
+++ b/net/bridge/br_netlink.c
|
||||
@@ -657,6 +657,8 @@ void br_info_notify(int event, const str
|
||||
kfree_skb(skb);
|
||||
goto errout;
|
||||
}
|
||||
+
|
||||
+ __br_notify(RTNLGRP_LINK, event, port);
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
|
||||
return;
|
||||
errout:
|
||||
--- a/net/bridge/br_private.h
|
||||
+++ b/net/bridge/br_private.h
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/refcount.h>
|
||||
+#include <linux/export.h>
|
||||
|
||||
#define BR_HASH_BITS 8
|
||||
#define BR_HASH_SIZE (1 << BR_HASH_BITS)
|
||||
@@ -2273,4 +2274,12 @@ bool br_is_neigh_suppress_enabled(const
|
||||
#define __br_get(__hook, __default, __args ...) \
|
||||
(__hook ? (__hook(__args)) : (__default))
|
||||
|
||||
+static inline void __br_notify(int group, int type, const void *data)
|
||||
+{
|
||||
+ br_notify_hook_t *notify_hook = rcu_dereference(br_notify_hook);
|
||||
+
|
||||
+ if (notify_hook)
|
||||
+ notify_hook(group, type, data);
|
||||
+}
|
||||
+
|
||||
#endif
|
||||
@@ -0,0 +1,109 @@
|
||||
From f765b8ae3df6783fed448413937781aa984389ea Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Thu, 5 May 2016 14:01:51 -0700
|
||||
Subject: [PATCH 231/281] neighbour: Add a new neigh mac update notifier
|
||||
|
||||
With this new notifier, neighbour subsystem will
|
||||
provide a neighbour mac address update notification
|
||||
with both the old and new mac adress. This helps the
|
||||
other subsystems to do whatever they want with the old
|
||||
mac address, if they used it in their own purpose.
|
||||
|
||||
Change-Id: I86f6f7107b4c840d05bce167594fdd43d7bb0ff3
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/net/neighbour.h | 8 ++++++++
|
||||
net/core/neighbour.c | 28 +++++++++++++++++++++++++++-
|
||||
2 files changed, 35 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/net/neighbour.h
|
||||
+++ b/include/net/neighbour.h
|
||||
@@ -249,6 +249,11 @@ static inline int neigh_parms_family(str
|
||||
return p->tbl->family;
|
||||
}
|
||||
|
||||
+struct neigh_mac_update {
|
||||
+ unsigned char old_mac[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
|
||||
+ unsigned char update_mac[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
|
||||
+};
|
||||
+
|
||||
#define NEIGH_PRIV_ALIGN sizeof(long long)
|
||||
#define NEIGH_ENTRY_SIZE(size) ALIGN((size), NEIGH_PRIV_ALIGN)
|
||||
|
||||
@@ -395,6 +400,9 @@ void __neigh_for_each_release(struct nei
|
||||
int (*cb)(struct neighbour *));
|
||||
int neigh_xmit(int fam, struct net_device *, const void *, struct sk_buff *);
|
||||
|
||||
+extern void neigh_mac_update_register_notify(struct notifier_block *nb);
|
||||
+extern void neigh_mac_update_unregister_notify(struct notifier_block *nb);
|
||||
+
|
||||
struct neigh_seq_state {
|
||||
struct seq_net_private p;
|
||||
struct neigh_table *tbl;
|
||||
--- a/net/core/neighbour.c
|
||||
+++ b/net/core/neighbour.c
|
||||
@@ -1275,6 +1275,20 @@ static void neigh_update_hhs(struct neig
|
||||
}
|
||||
}
|
||||
|
||||
+ATOMIC_NOTIFIER_HEAD(neigh_mac_update_notifier_list);
|
||||
+
|
||||
+void neigh_mac_update_register_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_register(&neigh_mac_update_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(neigh_mac_update_register_notify);
|
||||
+
|
||||
+void neigh_mac_update_unregister_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_unregister(&neigh_mac_update_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(neigh_mac_update_unregister_notify);
|
||||
+
|
||||
/* Generic update routine.
|
||||
-- lladdr is new lladdr or NULL, if it is not supplied.
|
||||
-- new is new state.
|
||||
@@ -1303,6 +1317,7 @@ static int __neigh_update(struct neighbo
|
||||
struct net_device *dev;
|
||||
int err, notify = 0;
|
||||
u8 old;
|
||||
+ struct neigh_mac_update nmu;
|
||||
|
||||
trace_neigh_update(neigh, lladdr, new, flags, nlmsg_pid);
|
||||
|
||||
@@ -1312,6 +1327,8 @@ static int __neigh_update(struct neighbo
|
||||
old = neigh->nud_state;
|
||||
err = -EPERM;
|
||||
|
||||
+ memset(&nmu, 0, sizeof(struct neigh_mac_update));
|
||||
+
|
||||
if (neigh->dead) {
|
||||
NL_SET_ERR_MSG(extack, "Neighbor entry is now dead");
|
||||
new = old;
|
||||
@@ -1353,7 +1370,11 @@ static int __neigh_update(struct neighbo
|
||||
and a new address is proposed:
|
||||
- compare new & old
|
||||
- if they are different, check override flag
|
||||
+ - copy old and new addresses for neigh update notification
|
||||
*/
|
||||
+ memcpy(nmu.old_mac, neigh->ha, dev->addr_len);
|
||||
+ memcpy(nmu.update_mac, lladdr, dev->addr_len);
|
||||
+
|
||||
if ((old & NUD_VALID) &&
|
||||
!memcmp(lladdr, neigh->ha, dev->addr_len))
|
||||
lladdr = neigh->ha;
|
||||
@@ -1476,8 +1497,13 @@ out:
|
||||
neigh_update_gc_list(neigh);
|
||||
if (managed_update)
|
||||
neigh_update_managed_list(neigh);
|
||||
- if (notify)
|
||||
+
|
||||
+ if (notify) {
|
||||
neigh_update_notify(neigh, nlmsg_pid);
|
||||
+ atomic_notifier_call_chain(&neigh_mac_update_notifier_list, 0,
|
||||
+ (struct neigh_mac_update *)&nmu);
|
||||
+ }
|
||||
+
|
||||
trace_neigh_update_done(neigh, err);
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
From c1be565d9240421e69de2ff13b53919134c03edd Mon Sep 17 00:00:00 2001
|
||||
From: Ram Chandra Jangir <rjangir@codeaurora.org>
|
||||
Date: Sat, 30 Jul 2016 19:31:53 +0530
|
||||
Subject: [PATCH 232/281] netfilter: iptable: Fix IPv4 default checks
|
||||
|
||||
OpenWRT: 610-netfilter_match_bypass_default_checks.patch
|
||||
This change fixes up the above patch that had some code get dropped
|
||||
when FFW linux v4.4.6 to v4.4.14
|
||||
|
||||
Change-Id: Ic2172192f23b9ccaa7a9d56139d1f09952636396
|
||||
Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org>
|
||||
---
|
||||
net/ipv4/netfilter/ip_tables.c | 32 +++++++++++++++++++++++++++++---
|
||||
1 file changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/net/ipv4/netfilter/ip_tables.c
|
||||
+++ b/net/ipv4/netfilter/ip_tables.c
|
||||
@@ -524,6 +524,28 @@ static void cleanup_match(struct xt_entr
|
||||
}
|
||||
|
||||
static int
|
||||
+check_entry(struct ipt_entry *e)
|
||||
+{
|
||||
+ const struct xt_entry_target *t;
|
||||
+
|
||||
+ if (!ip_checkentry(&e->ip))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ ip_checkdefault(&e->ip);
|
||||
+
|
||||
+ if (e->target_offset + sizeof(struct xt_entry_target) >
|
||||
+ e->next_offset)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ t = ipt_get_target_c(e);
|
||||
+
|
||||
+ if (e->target_offset + t->u.target_size > e->next_offset)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ipt_ip *ip = par->entryinfo;
|
||||
@@ -586,7 +608,9 @@ find_check_entry(struct ipt_entry *e, st
|
||||
struct xt_mtchk_param mtpar;
|
||||
struct xt_entry_match *ematch;
|
||||
|
||||
- ip_checkdefault(&e->ip);
|
||||
+ ret = check_entry(e);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
if (!xt_percpu_counter_alloc(alloc_state, &e->counters))
|
||||
return -ENOMEM;
|
||||
@@ -1382,8 +1406,10 @@ check_compat_entry_size_and_hooks(struct
|
||||
sizeof(struct compat_xt_entry_target))
|
||||
return -EINVAL;
|
||||
|
||||
- if (!ip_checkentry(&e->ip))
|
||||
- return -EINVAL;
|
||||
+ /* For purposes of check_entry casting the compat entry is fine */
|
||||
+ ret = check_entry((struct ipt_entry *)e);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
ret = xt_compat_check_entry_offsets(e, e->elems,
|
||||
e->target_offset, e->next_offset);
|
||||
@@ -0,0 +1,26 @@
|
||||
From 8e6a2101624053c79ea39fe4aed435a3bd5a6f3f Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Fri, 24 Apr 2020 10:59:16 -0700
|
||||
Subject: [PATCH 233/281] net: Export dev_shutdown()
|
||||
|
||||
This API is needed by interface drivers to ensure qdiscs are destroyed
|
||||
before the NSS interfaces are destroyed. Since Linux destroys qdiscs
|
||||
only at unregister_netdevice(), it is too late for destroying any NSS
|
||||
qdiscs that may be configured on the interface.
|
||||
|
||||
Change-Id: I66a6ec5b5393f9848ff1202e2753c738786c515f
|
||||
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
|
||||
---
|
||||
net/sched/sch_generic.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/net/sched/sch_generic.c
|
||||
+++ b/net/sched/sch_generic.c
|
||||
@@ -1494,6 +1494,7 @@ void dev_shutdown(struct net_device *dev
|
||||
|
||||
WARN_ON(timer_pending(&dev->watchdog_timer));
|
||||
}
|
||||
+EXPORT_SYMBOL(dev_shutdown);
|
||||
|
||||
/**
|
||||
* psched_ratecfg_precompute__() - Pre-compute values for reciprocal division
|
||||
@@ -0,0 +1,182 @@
|
||||
From a647c9cf03fd82ce5e090891e5ffa68e22dcf88d Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Mon, 8 May 2017 11:49:21 -0700
|
||||
Subject: [PATCH 234/281] OpenWRT: 644-bridge_optimize_netfilter_hooks.patch
|
||||
|
||||
This patch applies the following upstreamed
|
||||
openwrt patch from 3.14 kernel.
|
||||
|
||||
commit 76b37c24252b (OpenWrt: apply 644-bridge_optimize_netfilter_hooks.patch)
|
||||
|
||||
Change-Id: I4dde201c34717321115c9c067dc10d0b38d6eee6
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
net/bridge/br_forward.c | 4 ++--
|
||||
net/bridge/br_input.c | 6 +++---
|
||||
net/bridge/br_multicast.c | 2 +-
|
||||
net/bridge/br_netfilter_hooks.c | 17 +++++++++++++++++
|
||||
net/bridge/br_private.h | 14 ++++++++++++++
|
||||
net/bridge/br_stp_bpdu.c | 2 +-
|
||||
6 files changed, 38 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/net/bridge/br_forward.c
|
||||
+++ b/net/bridge/br_forward.c
|
||||
@@ -63,7 +63,7 @@ EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit
|
||||
int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
skb_clear_tstamp(skb);
|
||||
- return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING,
|
||||
+ return BR_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING,
|
||||
net, sk, skb, NULL, skb->dev,
|
||||
br_dev_queue_push_xmit);
|
||||
|
||||
@@ -112,7 +112,7 @@ static void __br_forward(const struct ne
|
||||
indev = NULL;
|
||||
}
|
||||
|
||||
- NF_HOOK(NFPROTO_BRIDGE, br_hook,
|
||||
+ BR_HOOK(NFPROTO_BRIDGE, br_hook,
|
||||
net, NULL, skb, indev, skb->dev,
|
||||
br_forward_finish);
|
||||
}
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -75,7 +75,7 @@ int br_pass_frame_up(struct sk_buff *skb
|
||||
|
||||
BR_INPUT_SKB_CB(skb)->promisc = promisc;
|
||||
|
||||
- return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
|
||||
+ return BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
|
||||
dev_net(indev), NULL, skb, indev, NULL,
|
||||
br_netif_receive_skb);
|
||||
}
|
||||
@@ -433,7 +433,7 @@ static rx_handler_result_t br_handle_fra
|
||||
* - returns = 0 (stolen/nf_queue)
|
||||
* Thus return 1 from the okfn() to signal the skb is ok to pass
|
||||
*/
|
||||
- if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
|
||||
+ if (BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
|
||||
dev_net(skb->dev), NULL, skb, skb->dev, NULL,
|
||||
br_handle_local_finish) == 1) {
|
||||
return RX_HANDLER_PASS;
|
||||
@@ -454,7 +454,7 @@ forward:
|
||||
if (ether_addr_equal(p->br->dev->dev_addr, dest))
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
|
||||
- if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING,
|
||||
+ if (BR_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING,
|
||||
dev_net(skb->dev), NULL, skb, skb->dev, NULL,
|
||||
br_handle_local_finish) == 1) {
|
||||
return RX_HANDLER_PASS;
|
||||
--- a/net/bridge/br_multicast.c
|
||||
+++ b/net/bridge/br_multicast.c
|
||||
@@ -1805,7 +1805,7 @@ again_under_lmqt:
|
||||
skb->dev = pmctx->port->dev;
|
||||
br_multicast_count(brmctx->br, pmctx->port, skb, igmp_type,
|
||||
BR_MCAST_DIR_TX);
|
||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
|
||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
|
||||
dev_net(pmctx->port->dev), NULL, skb, NULL, skb->dev,
|
||||
br_dev_queue_push_xmit);
|
||||
|
||||
--- a/net/bridge/br_netfilter_hooks.c
|
||||
+++ b/net/bridge/br_netfilter_hooks.c
|
||||
@@ -61,6 +61,7 @@ struct brnf_net {
|
||||
int call_iptables;
|
||||
int call_ip6tables;
|
||||
int call_arptables;
|
||||
+ int call_ebtables;
|
||||
|
||||
/* default value is 0 */
|
||||
int filter_vlan_tagged;
|
||||
@@ -77,6 +78,14 @@ struct brnf_net {
|
||||
#define IS_ARP(skb) \
|
||||
(!skb_vlan_tag_present(skb) && skb->protocol == htons(ETH_P_ARP))
|
||||
|
||||
+bool br_netfilter_run_hooks(struct net *net)
|
||||
+{
|
||||
+ struct brnf_net *brnf = net_generic(net, brnf_net_id);
|
||||
+
|
||||
+ return brnf->call_iptables | brnf->call_ip6tables | brnf->call_arptables |
|
||||
+ brnf->call_ebtables;
|
||||
+}
|
||||
+
|
||||
static inline __be16 vlan_proto(const struct sk_buff *skb)
|
||||
{
|
||||
if (skb_vlan_tag_present(skb))
|
||||
@@ -1238,6 +1247,12 @@ static struct ctl_table brnf_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
+ {
|
||||
+ .procname = "bridge-nf-call-ebtables",
|
||||
+ .maxlen = sizeof(int),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = brnf_sysctl_call_tables,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -1246,6 +1261,7 @@ static inline void br_netfilter_sysctl_d
|
||||
brnf->call_iptables = 1;
|
||||
brnf->call_ip6tables = 1;
|
||||
brnf->call_arptables = 1;
|
||||
+ brnf->call_ebtables = 0;
|
||||
brnf->filter_vlan_tagged = 0;
|
||||
brnf->filter_pppoe_tagged = 0;
|
||||
brnf->pass_vlan_indev = 0;
|
||||
@@ -1269,6 +1285,7 @@ static int br_netfilter_sysctl_init_net(
|
||||
table[3].data = &brnet->filter_vlan_tagged;
|
||||
table[4].data = &brnet->filter_pppoe_tagged;
|
||||
table[5].data = &brnet->pass_vlan_indev;
|
||||
+ table[6].data = &brnet->call_ebtables;
|
||||
|
||||
br_netfilter_sysctl_default(brnet);
|
||||
|
||||
--- a/net/bridge/br_private.h
|
||||
+++ b/net/bridge/br_private.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/export.h>
|
||||
+#include <linux/netfilter.h>
|
||||
|
||||
#define BR_HASH_BITS 8
|
||||
#define BR_HASH_SIZE (1 << BR_HASH_BITS)
|
||||
@@ -1934,12 +1935,25 @@ extern const struct nf_br_ops __rcu *nf_
|
||||
int br_nf_core_init(void);
|
||||
void br_nf_core_fini(void);
|
||||
void br_netfilter_rtable_init(struct net_bridge *);
|
||||
+bool br_netfilter_run_hooks(struct net *net);
|
||||
#else
|
||||
static inline int br_nf_core_init(void) { return 0; }
|
||||
static inline void br_nf_core_fini(void) {}
|
||||
#define br_netfilter_rtable_init(x)
|
||||
+static inline bool br_netfilter_run_hooks(struct net *net) { return false; }
|
||||
#endif
|
||||
|
||||
+static inline int
|
||||
+BR_HOOK(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk,
|
||||
+ struct sk_buff *skb, struct net_device *in, struct net_device *out,
|
||||
+ int (*okfn)(struct net *, struct sock *, struct sk_buff *))
|
||||
+{
|
||||
+ if (!br_netfilter_run_hooks(net))
|
||||
+ return okfn(net, sk, skb);
|
||||
+
|
||||
+ return NF_HOOK(pf, hook, net, sk, skb, in, out, okfn);
|
||||
+}
|
||||
+
|
||||
/* br_stp.c */
|
||||
void br_set_state(struct net_bridge_port *p, unsigned int state);
|
||||
struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no);
|
||||
--- a/net/bridge/br_stp_bpdu.c
|
||||
+++ b/net/bridge/br_stp_bpdu.c
|
||||
@@ -56,7 +56,7 @@ static void br_send_bpdu(struct net_brid
|
||||
|
||||
skb_reset_mac_header(skb);
|
||||
|
||||
- NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
|
||||
+ BR_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT,
|
||||
dev_net(p->dev), NULL, skb, NULL, skb->dev,
|
||||
br_send_bpdu_finish);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
--- a/include/linux/netfilter/nf_conntrack_proto_gre.h
|
||||
+++ b/include/linux/netfilter/nf_conntrack_proto_gre.h
|
||||
@@ -30,4 +30,36 @@ void nf_ct_gre_keymap_destroy(struct nf_
|
||||
|
||||
bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
|
||||
struct net *net, struct nf_conntrack_tuple *tuple);
|
||||
+
|
||||
+
|
||||
+/* GRE is a mess: Four different standards */
|
||||
+struct gre_hdr {
|
||||
+#if defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
+ __u16 rec:3,
|
||||
+ srr:1,
|
||||
+ seq:1,
|
||||
+ key:1,
|
||||
+ routing:1,
|
||||
+ csum:1,
|
||||
+ version:3,
|
||||
+ reserved:4,
|
||||
+ ack:1;
|
||||
+#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
+ __u16 csum:1,
|
||||
+ routing:1,
|
||||
+ key:1,
|
||||
+ seq:1,
|
||||
+ srr:1,
|
||||
+ rec:3,
|
||||
+ ack:1,
|
||||
+ reserved:4,
|
||||
+ version:3;
|
||||
+#else
|
||||
+#error "Adjust your <asm/byteorder.h> defines"
|
||||
+#endif
|
||||
+ __be16 protocol;
|
||||
+};
|
||||
+
|
||||
+
|
||||
+
|
||||
#endif /* _CONNTRACK_PROTO_GRE_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
From b10ef8fe182915a8af2a0cc2ebca16d45f4aaba1 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Fri, 2 Jun 2017 10:22:27 -0700
|
||||
Subject: [PATCH 235/281] bridge: Add flag to force netfilter hook evaluation
|
||||
|
||||
Add a sysctl (similar to the ones for iptables/ip6tables) to allow user
|
||||
space to force evaluation of Netfilter hooks registered with the bridge.
|
||||
This allows custom module's hooks to be invoked without the
|
||||
iptables/ip6tables/arptables special processing being enabled.
|
||||
Without this, any such modules will never have their hooks invoked
|
||||
unless one of the other flags is set via sysctl.
|
||||
|
||||
Change-Id: I2875c77525c96c8f69774ab41d5d77e240d88dbb
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
net/bridge/br_netfilter_hooks.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/net/bridge/br_netfilter_hooks.c
|
||||
+++ b/net/bridge/br_netfilter_hooks.c
|
||||
@@ -62,6 +62,7 @@ struct brnf_net {
|
||||
int call_ip6tables;
|
||||
int call_arptables;
|
||||
int call_ebtables;
|
||||
+ int call_custom;
|
||||
|
||||
/* default value is 0 */
|
||||
int filter_vlan_tagged;
|
||||
@@ -83,7 +84,7 @@ bool br_netfilter_run_hooks(struct net *
|
||||
struct brnf_net *brnf = net_generic(net, brnf_net_id);
|
||||
|
||||
return brnf->call_iptables | brnf->call_ip6tables | brnf->call_arptables |
|
||||
- brnf->call_ebtables;
|
||||
+ brnf->call_ebtables | brnf->call_custom;
|
||||
}
|
||||
|
||||
static inline __be16 vlan_proto(const struct sk_buff *skb)
|
||||
@@ -1253,6 +1254,12 @@ static struct ctl_table brnf_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = brnf_sysctl_call_tables,
|
||||
},
|
||||
+ {
|
||||
+ .procname = "bridge-nf-call-custom",
|
||||
+ .maxlen = sizeof(int),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = brnf_sysctl_call_tables,
|
||||
+ },
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -1262,6 +1269,7 @@ static inline void br_netfilter_sysctl_d
|
||||
brnf->call_ip6tables = 1;
|
||||
brnf->call_arptables = 1;
|
||||
brnf->call_ebtables = 0;
|
||||
+ brnf->call_custom = 0;
|
||||
brnf->filter_vlan_tagged = 0;
|
||||
brnf->filter_pppoe_tagged = 0;
|
||||
brnf->pass_vlan_indev = 0;
|
||||
@@ -1286,6 +1294,7 @@ static int br_netfilter_sysctl_init_net(
|
||||
table[4].data = &brnet->filter_pppoe_tagged;
|
||||
table[5].data = &brnet->pass_vlan_indev;
|
||||
table[6].data = &brnet->call_ebtables;
|
||||
+ table[7].data = &brnet->call_custom;
|
||||
|
||||
br_netfilter_sysctl_default(brnet);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
From a64c7ddebaa8749d35fc54b7fcb7f1b7ce076da3 Mon Sep 17 00:00:00 2001
|
||||
From: Zhu Ken <guigenz@codeaurora.org>
|
||||
Date: Tue, 27 Oct 2015 13:40:51 -0700
|
||||
Subject: [PATCH 236/281] net: bridge: don't loopback multicast when hairpin
|
||||
enabled
|
||||
|
||||
some virtual service test cases need to enable bridge hairpin.
|
||||
But hairpin will break the DHCP procedure on lan side as follows :
|
||||
Because the first DHCP discovery packet is a broadcast packet, so this
|
||||
packet will be loopbacked to switch port 6 which was connected to bridge
|
||||
member eth1, this will result in a switch fdb entry whose out port is
|
||||
switch port 6. Then the DHCP ack packet from our board DHCP server will
|
||||
be dropped by switch because its destination mac hit above switch fdb.
|
||||
The out port given by the fdb equals to the income port of DHCP ack
|
||||
packet, so this packet was dropped by switch.
|
||||
|
||||
Here forbade multicast to be loopbacked when hairpin enabled.
|
||||
|
||||
resolved some confliction and changed the author to resolve the invalid
|
||||
email
|
||||
|
||||
Change-Id: I4b5b4e71b8034588fc2c32b21a55dfe4cca32987
|
||||
Signed-off-by: Zhu Ken <guigenz@codeaurora.org>
|
||||
---
|
||||
net/bridge/br_forward.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/net/bridge/br_forward.c
|
||||
+++ b/net/bridge/br_forward.c
|
||||
@@ -24,7 +24,8 @@ static inline int should_deliver(const s
|
||||
struct net_bridge_vlan_group *vg;
|
||||
|
||||
vg = nbp_vlan_group_rcu(p);
|
||||
- return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
|
||||
+ return (((p->flags & BR_HAIRPIN_MODE) && !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
|
||||
+ || skb->dev != p->dev) &&
|
||||
(br_mst_is_enabled(p->br) || p->state == BR_STATE_FORWARDING) &&
|
||||
br_allowed_egress(vg, skb) && nbp_switchdev_allowed_egress(p, skb) &&
|
||||
!br_skb_isolated(p, skb);
|
||||
@@ -0,0 +1,61 @@
|
||||
From 0746a30988584dc8740c8bdc8d75a36452a84ca0 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Tue, 9 Feb 2016 18:00:05 -0800
|
||||
Subject: [PATCH 237/281] Fixed the br_dev_xmit function to call Hy-Fi hooks
|
||||
|
||||
- Previously this wasn't calling the Hy-Fi hooks (meaning that all
|
||||
locally generated traffic was sent on a FDB selected port, and hence
|
||||
in a Hy-Fi environment, could be spread across all backhauls)
|
||||
- Fixed to be the same as the banana kernel, and call the
|
||||
br_get_dst_hook_t
|
||||
|
||||
Change-Id: If5e964f385614beb5ebe9e1083ca947464165b9e
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Signed-off-by: Mughilan Ramajayam <mughilan@codeaurora.org>
|
||||
---
|
||||
net/bridge/br_device.c | 20 +++++++++++++++++---
|
||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/net/bridge/br_device.c
|
||||
+++ b/net/bridge/br_device.c
|
||||
@@ -38,6 +38,8 @@ netdev_tx_t br_dev_xmit(struct sk_buff *
|
||||
struct net_bridge_vlan *vlan;
|
||||
const unsigned char *dest;
|
||||
u16 vid = 0;
|
||||
+ struct net_bridge_port *pdst;
|
||||
+ br_get_dst_hook_t *get_dst_hook;
|
||||
|
||||
if (unlikely(reason != SKB_NOT_DROPPED_YET)) {
|
||||
kfree_skb_reason(skb, reason);
|
||||
@@ -85,6 +87,8 @@ netdev_tx_t br_dev_xmit(struct sk_buff *
|
||||
br_do_suppress_nd(skb, br, vid, NULL, msg);
|
||||
}
|
||||
|
||||
+ get_dst_hook = rcu_dereference(br_get_dst_hook);
|
||||
+
|
||||
dest = eth_hdr(skb)->h_dest;
|
||||
if (is_broadcast_ether_addr(dest)) {
|
||||
br_flood(br, skb, BR_PKT_BROADCAST, false, true, vid);
|
||||
@@ -109,10 +113,19 @@ netdev_tx_t br_dev_xmit(struct sk_buff *
|
||||
br_multicast_flood(mdst, skb, brmctx, false, true);
|
||||
else
|
||||
br_flood(br, skb, BR_PKT_MULTICAST, false, true, vid);
|
||||
- } else if ((dst = br_fdb_find_rcu(br, dest, vid)) != NULL) {
|
||||
- br_forward(dst->dst, skb, false, true);
|
||||
} else {
|
||||
- br_flood(br, skb, BR_PKT_UNICAST, false, true, vid);
|
||||
+ pdst = __br_get(get_dst_hook, NULL, NULL, &skb);
|
||||
+ if (pdst) {
|
||||
+ if (!skb)
|
||||
+ goto out;
|
||||
+ br_forward(pdst, skb, false, true);
|
||||
+ } else {
|
||||
+ dst = br_fdb_find_rcu(br, dest, vid);
|
||||
+ if (dst)
|
||||
+ br_forward(dst->dst, skb, false, true);
|
||||
+ else
|
||||
+ br_flood(br, skb, BR_PKT_UNICAST, false, true, vid);
|
||||
+ }
|
||||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
@@ -0,0 +1,102 @@
|
||||
From 70105ee0b32d3c84625fcf33622263dfceb9abc7 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Thu, 12 Mar 2020 17:25:42 -0700
|
||||
Subject: [PATCH 238/281] bridge: Extend struct br_fdb_event
|
||||
|
||||
Send an FDB update event with device information
|
||||
|
||||
Change-Id: I67df950c35af944543e31eef2f447494cea8bde1
|
||||
Signed-off-by: Casey Chen <kexinc@codeaurora.org>
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/linux/if_bridge.h | 7 +++++--
|
||||
net/bridge/br_fdb.c | 22 ++++++++++++++++++----
|
||||
2 files changed, 23 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -243,13 +243,16 @@ extern br_multicast_handle_hook_t __rcu
|
||||
#define BR_FDB_EVENT_DEL 0x02
|
||||
|
||||
struct br_fdb_event {
|
||||
+ unsigned char addr[6];
|
||||
+ unsigned char is_local;
|
||||
struct net_device *dev;
|
||||
- unsigned char addr[6];
|
||||
- unsigned char is_local;
|
||||
+ struct net_bridge *br;
|
||||
+ struct net_device *orig_dev;
|
||||
};
|
||||
|
||||
extern void br_fdb_register_notify(struct notifier_block *nb);
|
||||
extern void br_fdb_unregister_notify(struct notifier_block *nb);
|
||||
+extern struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br);
|
||||
|
||||
typedef struct net_bridge_port *br_get_dst_hook_t(
|
||||
const struct net_bridge_port *src,
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -574,8 +574,7 @@ void br_fdb_cleanup(struct work_struct *
|
||||
unsigned long delay = hold_time(br);
|
||||
unsigned long work_delay = delay;
|
||||
unsigned long now = jiffies;
|
||||
- u8 mac_addr[6];
|
||||
-
|
||||
+ struct br_fdb_event fdb_event;
|
||||
|
||||
/* this part is tricky, in order to avoid blocking learning and
|
||||
* consequently forwarding, we rely on rcu to delete objects with
|
||||
@@ -603,10 +602,11 @@ void br_fdb_cleanup(struct work_struct *
|
||||
} else {
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
if (!hlist_unhashed(&f->fdb_node)) {
|
||||
- ether_addr_copy(mac_addr, f->key.addr.addr);
|
||||
+ memset(&fdb_event, 0, sizeof(fdb_event));
|
||||
+ ether_addr_copy(fdb_event.addr, f->key.addr.addr);
|
||||
fdb_delete(br, f, true);
|
||||
atomic_notifier_call_chain(&br_fdb_update_notifier_list, 0,
|
||||
- (void *)mac_addr);
|
||||
+ (void *)&fdb_event);
|
||||
}
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
@@ -903,10 +903,19 @@ static bool __fdb_mark_active(struct net
|
||||
test_and_clear_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags));
|
||||
}
|
||||
|
||||
+/* Get the bridge device */
|
||||
+struct net_device *br_fdb_bridge_dev_get_and_hold(struct net_bridge *br)
|
||||
+{
|
||||
+ dev_hold(br->dev);
|
||||
+ return br->dev;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_bridge_dev_get_and_hold);
|
||||
+
|
||||
void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
||||
const unsigned char *addr, u16 vid, unsigned long flags)
|
||||
{
|
||||
struct net_bridge_fdb_entry *fdb;
|
||||
+ struct br_fdb_event fdb_event;
|
||||
|
||||
/* some users want to always flood. */
|
||||
if (hold_time(br) == 0)
|
||||
@@ -932,6 +941,10 @@ void br_fdb_update(struct net_bridge *br
|
||||
if (unlikely(source != READ_ONCE(fdb->dst) &&
|
||||
!test_bit(BR_FDB_STICKY, &fdb->flags))) {
|
||||
br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH);
|
||||
+ ether_addr_copy(fdb_event.addr, addr);
|
||||
+ fdb_event.br = br;
|
||||
+ fdb_event.orig_dev = fdb->dst->dev;
|
||||
+ fdb_event.dev = source->dev;
|
||||
WRITE_ONCE(fdb->dst, source);
|
||||
fdb_modified = true;
|
||||
/* Take over HW learned entry */
|
||||
@@ -942,7 +955,7 @@ void br_fdb_update(struct net_bridge *br
|
||||
|
||||
atomic_notifier_call_chain(
|
||||
&br_fdb_update_notifier_list,
|
||||
- 0, (void *)addr);
|
||||
+ 0, (void *)&fdb_event);
|
||||
|
||||
/* Clear locked flag when roaming to an
|
||||
* unlocked port.
|
||||
@@ -0,0 +1,691 @@
|
||||
From 002e9122621ca7a3d772c58d1790fac900025bd3 Mon Sep 17 00:00:00 2001
|
||||
From: Himanshu Joshi <himajosh@codeaurora.org>
|
||||
Date: Mon, 11 Apr 2016 19:28:47 +0530
|
||||
Subject: [PATCH] inet: Multicast acceleration support for 6.1
|
||||
|
||||
Added APIs for IPv4/v6 Multicast acceleration for 6.1 kernel
|
||||
|
||||
Change-Id: Iaa9182ed6643a59645f9b23b6ed53f9fccb3966a
|
||||
Signed-off-by: Shyam Sunder <ssunde@codeaurora.org>
|
||||
---
|
||||
include/linux/mroute.h | 38 +++++++
|
||||
include/linux/mroute6.h | 41 +++++++
|
||||
net/ipv4/ipmr.c | 230 ++++++++++++++++++++++++++++++++++++++
|
||||
net/ipv6/ip6mr.c | 241 +++++++++++++++++++++++++++++++++++++++-
|
||||
4 files changed, 547 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/include/linux/mroute.h
|
||||
+++ b/include/linux/mroute.h
|
||||
@@ -92,4 +92,42 @@ struct rtmsg;
|
||||
int ipmr_get_route(struct net *net, struct sk_buff *skb,
|
||||
__be32 saddr, __be32 daddr,
|
||||
struct rtmsg *rtm, u32 portid);
|
||||
+
|
||||
+#define IPMR_MFC_EVENT_UPDATE 1
|
||||
+#define IPMR_MFC_EVENT_DELETE 2
|
||||
+
|
||||
+/*
|
||||
+ * Callback to registered modules in the event of updates to a multicast group
|
||||
+ */
|
||||
+typedef void (*ipmr_mfc_event_offload_callback_t)(__be32 origin, __be32 group,
|
||||
+ u32 max_dest_dev,
|
||||
+ u32 dest_dev_idx[],
|
||||
+ u8 op);
|
||||
+
|
||||
+/*
|
||||
+ * Register the callback used to inform offload modules when updates occur to
|
||||
+ * MFC. The callback is registered by offload modules
|
||||
+ */
|
||||
+extern bool ipmr_register_mfc_event_offload_callback(
|
||||
+ ipmr_mfc_event_offload_callback_t mfc_offload_cb);
|
||||
+
|
||||
+/*
|
||||
+ * De-Register the callback used to inform offload modules when updates occur
|
||||
+ * to MFC
|
||||
+ */
|
||||
+extern void ipmr_unregister_mfc_event_offload_callback(void);
|
||||
+
|
||||
+/*
|
||||
+ * Find the destination interface list, given a multicast group and source
|
||||
+ */
|
||||
+extern int ipmr_find_mfc_entry(struct net *net, __be32 origin, __be32 group,
|
||||
+ u32 max_dst_cnt, u32 dest_dev[]);
|
||||
+
|
||||
+/*
|
||||
+ * Out-of-band multicast statistics update for flows that are offloaded from
|
||||
+ * Linux
|
||||
+ */
|
||||
+extern int ipmr_mfc_stats_update(struct net *net, __be32 origin, __be32 group,
|
||||
+ u64 pkts_in, u64 bytes_in,
|
||||
+ u64 pkts_out, u64 bytes_out);
|
||||
#endif
|
||||
--- a/include/linux/mroute6.h
|
||||
+++ b/include/linux/mroute6.h
|
||||
@@ -93,10 +93,51 @@ struct mfc6_cache {
|
||||
|
||||
#define MFC_ASSERT_THRESH (3*HZ) /* Maximal freq. of asserts */
|
||||
|
||||
+#define IP6MR_MFC_EVENT_UPDATE 1
|
||||
+#define IP6MR_MFC_EVENT_DELETE 2
|
||||
+
|
||||
struct rtmsg;
|
||||
extern int ip6mr_get_route(struct net *net, struct sk_buff *skb,
|
||||
struct rtmsg *rtm, u32 portid);
|
||||
|
||||
+/*
|
||||
+ * Callback to registered modules in the event of updates to a multicast group
|
||||
+ */
|
||||
+typedef void (*ip6mr_mfc_event_offload_callback_t)(struct in6_addr *origin,
|
||||
+ struct in6_addr *group,
|
||||
+ u32 max_dest_dev,
|
||||
+ u32 dest_dev_idx[],
|
||||
+ uint8_t op);
|
||||
+
|
||||
+/*
|
||||
+ * Register the callback used to inform offload modules when updates occur
|
||||
+ * to MFC. The callback is registered by offload modules
|
||||
+ */
|
||||
+extern bool ip6mr_register_mfc_event_offload_callback(
|
||||
+ ip6mr_mfc_event_offload_callback_t mfc_offload_cb);
|
||||
+
|
||||
+/*
|
||||
+ * De-Register the callback used to inform offload modules when updates occur
|
||||
+ * to MFC
|
||||
+ */
|
||||
+extern void ip6mr_unregister_mfc_event_offload_callback(void);
|
||||
+
|
||||
+/*
|
||||
+ * Find the destination interface list given a multicast group and source
|
||||
+ */
|
||||
+extern int ip6mr_find_mfc_entry(struct net *net, struct in6_addr *origin,
|
||||
+ struct in6_addr *group, u32 max_dst_cnt,
|
||||
+ u32 dest_dev[]);
|
||||
+
|
||||
+/*
|
||||
+ * Out-of-band multicast statistics update for flows that are offloaded from
|
||||
+ * Linux
|
||||
+ */
|
||||
+extern int ip6mr_mfc_stats_update(struct net *net, struct in6_addr *origin,
|
||||
+ struct in6_addr *group, uint64_t pkts_in,
|
||||
+ uint64_t bytes_in, uint64_t pkts_out,
|
||||
+ uint64_t bytes_out);
|
||||
+
|
||||
#ifdef CONFIG_IPV6_MROUTE
|
||||
bool mroute6_is_socket(struct net *net, struct sk_buff *skb);
|
||||
extern int ip6mr_sk_done(struct sock *sk);
|
||||
--- a/net/ipv4/ipmr.c
|
||||
+++ b/net/ipv4/ipmr.c
|
||||
@@ -89,6 +89,9 @@ static struct net_device *vif_dev_read(c
|
||||
/* Special spinlock for queue of unresolved entries */
|
||||
static DEFINE_SPINLOCK(mfc_unres_lock);
|
||||
|
||||
+/* spinlock for offload */
|
||||
+static DEFINE_SPINLOCK(lock);
|
||||
+
|
||||
/* We return to original Alan's scheme. Hash table of resolved
|
||||
* entries is changed only in process context and protected
|
||||
* with weak lock mrt_lock. Queue of unresolved entries is protected
|
||||
@@ -112,6 +115,9 @@ static void mroute_netlink_event(struct
|
||||
static void igmpmsg_netlink_event(const struct mr_table *mrt, struct sk_buff *pkt);
|
||||
static void mroute_clean_tables(struct mr_table *mrt, int flags);
|
||||
static void ipmr_expire_process(struct timer_list *t);
|
||||
+static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt, __be32 origin,
|
||||
+ __be32 mcastgrp);
|
||||
+static ipmr_mfc_event_offload_callback_t __rcu ipmr_mfc_event_offload_callback;
|
||||
|
||||
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
|
||||
#define ipmr_for_each_table(mrt, net) \
|
||||
@@ -233,6 +239,78 @@ static int ipmr_rule_fill(struct fib_rul
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* ipmr_sync_entry_update()
|
||||
+ * Call the registered offload callback to report an update to a multicast
|
||||
+ * route entry. The callback receives the list of destination interfaces and
|
||||
+ * the interface count
|
||||
+ */
|
||||
+static void ipmr_sync_entry_update(struct mr_table *mrt,
|
||||
+ struct mfc_cache *cache)
|
||||
+{
|
||||
+ int vifi, dest_if_count = 0;
|
||||
+ u32 dest_dev[MAXVIFS];
|
||||
+ __be32 origin;
|
||||
+ __be32 group;
|
||||
+ ipmr_mfc_event_offload_callback_t offload_update_cb_f;
|
||||
+
|
||||
+ memset(dest_dev, 0, sizeof(dest_dev));
|
||||
+
|
||||
+ origin = cache->mfc_origin;
|
||||
+ group = cache->mfc_mcastgrp;
|
||||
+
|
||||
+ spin_lock(&mrt_lock);
|
||||
+ for (vifi = 0; vifi < cache->_c.mfc_un.res.maxvif; vifi++) {
|
||||
+ if (!((cache->_c.mfc_un.res.ttls[vifi] > 0) &&
|
||||
+ (cache->_c.mfc_un.res.ttls[vifi] < 255))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (dest_if_count == MAXVIFS) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!VIF_EXISTS(mrt, vifi)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+ dest_dev[dest_if_count] = mrt->vif_table[vifi].dev->ifindex;
|
||||
+ dest_if_count++;
|
||||
+ }
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ offload_update_cb_f = rcu_dereference(ipmr_mfc_event_offload_callback);
|
||||
+
|
||||
+ if (!offload_update_cb_f) {
|
||||
+ rcu_read_unlock();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ offload_update_cb_f(group, origin, dest_if_count, dest_dev,
|
||||
+ IPMR_MFC_EVENT_UPDATE);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
+/* ipmr_sync_entry_delete()
|
||||
+ * Call the registered offload callback to inform of a multicast route entry
|
||||
+ * delete event
|
||||
+ */
|
||||
+static void ipmr_sync_entry_delete(u32 origin, u32 group)
|
||||
+{
|
||||
+ ipmr_mfc_event_offload_callback_t offload_update_cb_f;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ offload_update_cb_f = rcu_dereference(ipmr_mfc_event_offload_callback);
|
||||
+
|
||||
+ if (!offload_update_cb_f) {
|
||||
+ rcu_read_unlock();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ offload_update_cb_f(group, origin, 0, NULL, IPMR_MFC_EVENT_DELETE);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
static const struct fib_rules_ops __net_initconst ipmr_rules_ops_template = {
|
||||
.family = RTNL_FAMILY_IPMR,
|
||||
.rule_size = sizeof(struct ipmr_rule),
|
||||
@@ -246,6 +324,154 @@ static const struct fib_rules_ops __net_
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
+/* ipmr_register_mfc_event_offload_callback()
|
||||
+ * Register the IPv4 Multicast update offload callback with IPMR
|
||||
+ */
|
||||
+bool ipmr_register_mfc_event_offload_callback(
|
||||
+ ipmr_mfc_event_offload_callback_t mfc_offload_cb)
|
||||
+{
|
||||
+ ipmr_mfc_event_offload_callback_t offload_update_cb_f;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ offload_update_cb_f = rcu_dereference(ipmr_mfc_event_offload_callback);
|
||||
+
|
||||
+ if (offload_update_cb_f) {
|
||||
+ rcu_read_unlock();
|
||||
+ return false;
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ spin_lock(&lock);
|
||||
+ rcu_assign_pointer(ipmr_mfc_event_offload_callback, mfc_offload_cb);
|
||||
+ spin_unlock(&lock);
|
||||
+ synchronize_rcu();
|
||||
+ return true;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ipmr_register_mfc_event_offload_callback);
|
||||
+
|
||||
+/* ipmr_unregister_mfc_event_offload_callback()
|
||||
+ * De-register the IPv4 Multicast update offload callback with IPMR
|
||||
+ */
|
||||
+void ipmr_unregister_mfc_event_offload_callback(void)
|
||||
+{
|
||||
+ spin_lock(&lock);
|
||||
+ rcu_assign_pointer(ipmr_mfc_event_offload_callback, NULL);
|
||||
+ spin_unlock(&lock);
|
||||
+ synchronize_rcu();
|
||||
+}
|
||||
+EXPORT_SYMBOL(ipmr_unregister_mfc_event_offload_callback);
|
||||
+
|
||||
+/* ipmr_find_mfc_entry()
|
||||
+ * Returns destination interface list for a particular multicast flow, and
|
||||
+ * the number of interfaces in the list
|
||||
+ */
|
||||
+int ipmr_find_mfc_entry(struct net *net, __be32 origin, __be32 group,
|
||||
+ u32 max_dest_cnt, u32 dest_dev[])
|
||||
+{
|
||||
+ int vifi, dest_if_count = 0;
|
||||
+ struct mr_table *mrt;
|
||||
+ struct mfc_cache *cache;
|
||||
+
|
||||
+ mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
|
||||
+ if (!mrt)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ cache = ipmr_cache_find(mrt, origin, group);
|
||||
+ if (!cache) {
|
||||
+ rcu_read_unlock();
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock(&mrt_lock);
|
||||
+ for (vifi = 0; vifi < cache->_c.mfc_un.res.maxvif; vifi++) {
|
||||
+ if (!((cache->_c.mfc_un.res.ttls[vifi] > 0) &&
|
||||
+ (cache->_c.mfc_un.res.ttls[vifi] < 255))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* We have another valid destination interface entry. Check if
|
||||
+ * the number of the destination interfaces for the route is
|
||||
+ * exceeding the size of the array given to us
|
||||
+ */
|
||||
+ if (dest_if_count == max_dest_cnt) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!VIF_EXISTS(mrt, vifi)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ dest_dev[dest_if_count] = mrt->vif_table[vifi].dev->ifindex;
|
||||
+ dest_if_count++;
|
||||
+ }
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return dest_if_count;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ipmr_find_mfc_entry);
|
||||
+
|
||||
+/* ipmr_mfc_stats_update()
|
||||
+ * Update the MFC/VIF statistics for offloaded flows
|
||||
+ */
|
||||
+int ipmr_mfc_stats_update(struct net *net, __be32 origin, __be32 group,
|
||||
+ u64 pkts_in, u64 bytes_in,
|
||||
+ u64 pkts_out, u64 bytes_out)
|
||||
+{
|
||||
+ int vif, vifi;
|
||||
+ struct mr_table *mrt;
|
||||
+ struct mfc_cache *cache;
|
||||
+
|
||||
+ mrt = ipmr_get_table(net, RT_TABLE_DEFAULT);
|
||||
+ if (!mrt)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ cache = ipmr_cache_find(mrt, origin, group);
|
||||
+ if (!cache) {
|
||||
+ rcu_read_unlock();
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ vif = cache->_c.mfc_parent;
|
||||
+
|
||||
+ spin_lock(&mrt_lock);
|
||||
+ if (!VIF_EXISTS(mrt, vif)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ mrt->vif_table[vif].pkt_in += pkts_in;
|
||||
+ mrt->vif_table[vif].bytes_in += bytes_in;
|
||||
+ atomic_long_add(pkts_out, &cache->_c.mfc_un.res.pkt);
|
||||
+ atomic_long_add(bytes_out, &cache->_c.mfc_un.res.bytes);
|
||||
+
|
||||
+ for (vifi = cache->_c.mfc_un.res.minvif;
|
||||
+ vifi < cache->_c.mfc_un.res.maxvif; vifi++) {
|
||||
+ if ((cache->_c.mfc_un.res.ttls[vifi] > 0) &&
|
||||
+ (cache->_c.mfc_un.res.ttls[vifi] < 255)) {
|
||||
+ if (!VIF_EXISTS(mrt, vifi)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ rcu_read_unlock();
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ mrt->vif_table[vifi].pkt_out += pkts_out;
|
||||
+ mrt->vif_table[vifi].bytes_out += bytes_out;
|
||||
+ }
|
||||
+ }
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ipmr_mfc_stats_update);
|
||||
+
|
||||
static int __net_init ipmr_rules_init(struct net *net)
|
||||
{
|
||||
struct fib_rules_ops *ops;
|
||||
@@ -1203,6 +1429,8 @@ static int ipmr_mfc_delete(struct mr_tab
|
||||
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_DEL, c, mrt->id);
|
||||
mroute_netlink_event(mrt, c, RTM_DELROUTE);
|
||||
mr_cache_put(&c->_c);
|
||||
+ /* Inform offload modules of the delete event */
|
||||
+ ipmr_sync_entry_delete(c->mfc_origin, c->mfc_mcastgrp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1233,6 +1461,8 @@ static int ipmr_mfc_add(struct net *net,
|
||||
call_ipmr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE, c,
|
||||
mrt->id);
|
||||
mroute_netlink_event(mrt, c, RTM_NEWROUTE);
|
||||
+ /* Inform offload modules of the update event */
|
||||
+ ipmr_sync_entry_update(mrt, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--- a/net/ipv6/ip6mr.c
|
||||
+++ b/net/ipv6/ip6mr.c
|
||||
@@ -74,6 +74,9 @@ static struct net_device *vif_dev_read(c
|
||||
/* Special spinlock for queue of unresolved entries */
|
||||
static DEFINE_SPINLOCK(mfc_unres_lock);
|
||||
|
||||
+/* Spinlock for offload */
|
||||
+static DEFINE_SPINLOCK(lock);
|
||||
+
|
||||
/* We return to original Alan's scheme. Hash table of resolved
|
||||
entries is changed only in process context and protected
|
||||
with weak lock mrt_lock. Queue of unresolved entries is protected
|
||||
@@ -101,12 +104,15 @@ static int ip6mr_rtm_dumproute(struct sk
|
||||
struct netlink_callback *cb);
|
||||
static void mroute_clean_tables(struct mr_table *mrt, int flags);
|
||||
static void ipmr_expire_process(struct timer_list *t);
|
||||
+static struct mfc6_cache *ip6mr_cache_find(struct mr_table *mrt,
|
||||
+ const struct in6_addr *origin,
|
||||
+ const struct in6_addr *mcastgrp);
|
||||
+static ip6mr_mfc_event_offload_callback_t __rcu
|
||||
+ ip6mr_mfc_event_offload_callback;
|
||||
|
||||
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
||||
#define ip6mr_for_each_table(mrt, net) \
|
||||
- list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list, \
|
||||
- lockdep_rtnl_is_held() || \
|
||||
- list_empty(&net->ipv6.mr6_tables))
|
||||
+ list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
|
||||
|
||||
static struct mr_table *ip6mr_mr_table_iter(struct net *net,
|
||||
struct mr_table *mrt)
|
||||
@@ -387,6 +393,82 @@ static struct mfc6_cache_cmp_arg ip6mr_m
|
||||
.mf6c_mcastgrp = IN6ADDR_ANY_INIT,
|
||||
};
|
||||
|
||||
+/* ip6mr_sync_entry_update()
|
||||
+ * Call the registered offload callback to report an update to a multicast
|
||||
+ * route entry. The callback receives the list of destination interfaces and
|
||||
+ * the interface count
|
||||
+ */
|
||||
+static void ip6mr_sync_entry_update(struct mr_table *mrt,
|
||||
+ struct mfc6_cache *cache)
|
||||
+{
|
||||
+ int vifi, dest_if_count = 0;
|
||||
+ u32 dest_dev[MAXMIFS];
|
||||
+ struct in6_addr mc_origin, mc_group;
|
||||
+ ip6mr_mfc_event_offload_callback_t offload_update_cb_f;
|
||||
+
|
||||
+ memset(dest_dev, 0, sizeof(dest_dev));
|
||||
+
|
||||
+ spin_lock(&mrt_lock);
|
||||
+
|
||||
+ for (vifi = 0; vifi < cache->_c.mfc_un.res.maxvif; vifi++) {
|
||||
+ if (!((cache->_c.mfc_un.res.ttls[vifi] > 0) &&
|
||||
+ (cache->_c.mfc_un.res.ttls[vifi] < 255))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (dest_if_count == MAXMIFS) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!VIF_EXISTS(mrt, vifi)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dest_dev[dest_if_count] = mrt->vif_table[vifi].dev->ifindex;
|
||||
+ dest_if_count++;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(&mc_origin, &cache->mf6c_origin, sizeof(struct in6_addr));
|
||||
+ memcpy(&mc_group, &cache->mf6c_mcastgrp, sizeof(struct in6_addr));
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ offload_update_cb_f = rcu_dereference(ip6mr_mfc_event_offload_callback);
|
||||
+
|
||||
+ if (!offload_update_cb_f) {
|
||||
+ rcu_read_unlock();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ offload_update_cb_f(&mc_group, &mc_origin, dest_if_count, dest_dev,
|
||||
+ IP6MR_MFC_EVENT_UPDATE);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
+/* ip6mr_sync_entry_delete()
|
||||
+ * Call the registered offload callback to inform of a multicast route entry
|
||||
+ * delete event
|
||||
+ */
|
||||
+static void ip6mr_sync_entry_delete(struct in6_addr *mc_origin,
|
||||
+ struct in6_addr *mc_group)
|
||||
+{
|
||||
+ ip6mr_mfc_event_offload_callback_t offload_update_cb_f;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ offload_update_cb_f = rcu_dereference(ip6mr_mfc_event_offload_callback);
|
||||
+
|
||||
+ if (!offload_update_cb_f) {
|
||||
+ rcu_read_unlock();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ offload_update_cb_f(mc_group, mc_origin, 0, NULL,
|
||||
+ IP6MR_MFC_EVENT_DELETE);
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+
|
||||
static struct mr_table_ops ip6mr_mr_table_ops = {
|
||||
.rht_params = &ip6mr_rht_params,
|
||||
.cmparg_any = &ip6mr_mr_table_ops_cmparg_any,
|
||||
@@ -711,6 +793,149 @@ static int call_ip6mr_mfc_entry_notifier
|
||||
&mfc->_c, tb_id, &net->ipv6.ipmr_seq);
|
||||
}
|
||||
|
||||
+/* ip6mr_register_mfc_event_offload_callback()
|
||||
+ * Register the IPv6 multicast update callback for offload modules
|
||||
+ */
|
||||
+bool ip6mr_register_mfc_event_offload_callback(
|
||||
+ ip6mr_mfc_event_offload_callback_t mfc_offload_cb)
|
||||
+{
|
||||
+ ip6mr_mfc_event_offload_callback_t offload_update_cb_f;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ offload_update_cb_f = rcu_dereference(ip6mr_mfc_event_offload_callback);
|
||||
+
|
||||
+ if (offload_update_cb_f) {
|
||||
+ rcu_read_unlock();
|
||||
+ return false;
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+
|
||||
+ spin_lock(&lock);
|
||||
+ rcu_assign_pointer(ip6mr_mfc_event_offload_callback, mfc_offload_cb);
|
||||
+ spin_unlock(&lock);
|
||||
+ synchronize_rcu();
|
||||
+ return true;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip6mr_register_mfc_event_offload_callback);
|
||||
+
|
||||
+/* ip6mr_unregister_mfc_event_offload_callback()
|
||||
+ * De-register the IPv6 multicast update callback for offload modules
|
||||
+ */
|
||||
+void ip6mr_unregister_mfc_event_offload_callback(void)
|
||||
+{
|
||||
+ spin_lock(&lock);
|
||||
+ rcu_assign_pointer(ip6mr_mfc_event_offload_callback, NULL);
|
||||
+ spin_unlock(&lock);
|
||||
+ synchronize_rcu();
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip6mr_unregister_mfc_event_offload_callback);
|
||||
+
|
||||
+/* ip6mr_find_mfc_entry()
|
||||
+ * Return the destination interface list for a particular multicast flow, and
|
||||
+ * the number of interfaces in the list
|
||||
+ */
|
||||
+int ip6mr_find_mfc_entry(struct net *net, struct in6_addr *origin,
|
||||
+ struct in6_addr *group, u32 max_dest_cnt,
|
||||
+ u32 dest_dev[])
|
||||
+{
|
||||
+ int vifi, dest_if_count = 0;
|
||||
+ struct mr_table *mrt;
|
||||
+ struct mfc6_cache *cache;
|
||||
+
|
||||
+ mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
|
||||
+ if (!mrt)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ spin_lock(&mrt_lock);
|
||||
+ cache = ip6mr_cache_find(mrt, origin, group);
|
||||
+ if (!cache) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ for (vifi = 0; vifi < cache->_c.mfc_un.res.maxvif; vifi++) {
|
||||
+ if (!((cache->_c.mfc_un.res.ttls[vifi] > 0) &&
|
||||
+ (cache->_c.mfc_un.res.ttls[vifi] < 255))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ /* We have another valid destination interface entry. Check if
|
||||
+ * the number of the destination interfaces for the route is
|
||||
+ * exceeding the size of the array given to us
|
||||
+ */
|
||||
+ if (dest_if_count == max_dest_cnt) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!VIF_EXISTS(mrt, vifi)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ dest_dev[dest_if_count] = mrt->vif_table[vifi].dev->ifindex;
|
||||
+ dest_if_count++;
|
||||
+ }
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+
|
||||
+ return dest_if_count;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip6mr_find_mfc_entry);
|
||||
+
|
||||
+/* ip6mr_mfc_stats_update()
|
||||
+ * Update the MFC/VIF statistics for offloaded flows
|
||||
+ */
|
||||
+int ip6mr_mfc_stats_update(struct net *net, struct in6_addr *origin,
|
||||
+ struct in6_addr *group, u64 pkts_in,
|
||||
+ u64 bytes_in, uint64_t pkts_out,
|
||||
+ u64 bytes_out)
|
||||
+{
|
||||
+ int vif, vifi;
|
||||
+ struct mr_table *mrt;
|
||||
+ struct mfc6_cache *cache;
|
||||
+
|
||||
+ mrt = ip6mr_get_table(net, RT6_TABLE_DFLT);
|
||||
+
|
||||
+ if (!mrt)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ spin_lock(&mrt_lock);
|
||||
+ cache = ip6mr_cache_find(mrt, origin, group);
|
||||
+ if (!cache) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ vif = cache->_c.mfc_parent;
|
||||
+
|
||||
+ if (!VIF_EXISTS(mrt, vif)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ mrt->vif_table[vif].pkt_in += pkts_in;
|
||||
+ mrt->vif_table[vif].bytes_in += bytes_in;
|
||||
+ atomic_long_add(pkts_out, &cache->_c.mfc_un.res.pkt);
|
||||
+ atomic_long_add(bytes_out, &cache->_c.mfc_un.res.bytes);
|
||||
+
|
||||
+ for (vifi = cache->_c.mfc_un.res.minvif;
|
||||
+ vifi < cache->_c.mfc_un.res.maxvif; vifi++) {
|
||||
+ if ((cache->_c.mfc_un.res.ttls[vifi] > 0) &&
|
||||
+ (cache->_c.mfc_un.res.ttls[vifi] < 255)) {
|
||||
+ if (!VIF_EXISTS(mrt, vifi)) {
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ mrt->vif_table[vifi].pkt_out += pkts_out;
|
||||
+ mrt->vif_table[vifi].bytes_out += bytes_out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spin_unlock(&mrt_lock);
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip6mr_mfc_stats_update);
|
||||
+
|
||||
/* Delete a VIF entry */
|
||||
static int mif6_delete(struct mr_table *mrt, int vifi, int notify,
|
||||
struct list_head *head)
|
||||
@@ -1235,6 +1460,7 @@ static int ip6mr_mfc_delete(struct mr_ta
|
||||
int parent)
|
||||
{
|
||||
struct mfc6_cache *c;
|
||||
+ struct in6_addr mc_origin, mc_group;
|
||||
|
||||
/* The entries are added/deleted only under RTNL */
|
||||
rcu_read_lock();
|
||||
@@ -1243,6 +1469,9 @@ static int ip6mr_mfc_delete(struct mr_ta
|
||||
rcu_read_unlock();
|
||||
if (!c)
|
||||
return -ENOENT;
|
||||
+
|
||||
+ memcpy(&mc_origin, &c->mf6c_origin, sizeof(struct in6_addr));
|
||||
+ memcpy(&mc_group, &c->mf6c_mcastgrp, sizeof(struct in6_addr));
|
||||
rhltable_remove(&mrt->mfc_hash, &c->_c.mnode, ip6mr_rht_params);
|
||||
list_del_rcu(&c->_c.list);
|
||||
|
||||
@@ -1250,6 +1479,9 @@ static int ip6mr_mfc_delete(struct mr_ta
|
||||
FIB_EVENT_ENTRY_DEL, c, mrt->id);
|
||||
mr6_netlink_event(mrt, c, RTM_DELROUTE);
|
||||
mr_cache_put(&c->_c);
|
||||
+ /* Inform offload modules of the delete event */
|
||||
+ ip6mr_sync_entry_delete(&mc_origin, &mc_group);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1471,6 +1703,9 @@ static int ip6mr_mfc_add(struct net *net
|
||||
call_ip6mr_mfc_entry_notifiers(net, FIB_EVENT_ENTRY_REPLACE,
|
||||
c, mrt->id);
|
||||
mr6_netlink_event(mrt, c, RTM_NEWROUTE);
|
||||
+
|
||||
+ /* Inform offload modules of the update event */
|
||||
+ ip6mr_sync_entry_update(mrt, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
--- a/net/core/of_net.c
|
||||
+++ b/net/core/of_net.c
|
||||
@@ -40,7 +40,7 @@ int of_get_phy_mode(struct device_node *
|
||||
for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
|
||||
if (!strcasecmp(pm, phy_modes(i))) {
|
||||
*interface = i;
|
||||
- return 0;
|
||||
+ return i;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
38
target/linux/ipq806x/patches-6.6/990-037-fix-socinfo.patch
Normal file
38
target/linux/ipq806x/patches-6.6/990-037-fix-socinfo.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
--- a/drivers/soc/qcom/socinfo.c
|
||||
+++ b/drivers/soc/qcom/socinfo.c
|
||||
@@ -529,11 +529,13 @@ QCOM_OPEN(pmic_die_rev, qcom_show_pmic_d
|
||||
QCOM_OPEN(chip_id, qcom_show_chip_id);
|
||||
|
||||
#define DEFINE_IMAGE_OPS(type) \
|
||||
-static int show_image_##type(struct seq_file *seq, void *p) \
|
||||
+static int show_image_##type(struct seq_file *seq, void *p) \
|
||||
{ \
|
||||
struct smem_image_version *image_version = seq->private; \
|
||||
- if (image_version->type[0] != '\0') \
|
||||
- seq_printf(seq, "%s\n", image_version->type); \
|
||||
+ if(!image_version && !image_version->type[0]) { \
|
||||
+ seq_puts(seq, image_version->type); \
|
||||
+ seq_puts(seq, "\n"); \
|
||||
+ } \
|
||||
return 0; \
|
||||
} \
|
||||
static int open_image_##type(struct inode *inode, struct file *file) \
|
||||
@@ -749,7 +751,7 @@ static int qcom_socinfo_probe(struct pla
|
||||
if (!qs)
|
||||
return -ENOMEM;
|
||||
|
||||
- qs->attr.family = "Snapdragon";
|
||||
+ qs->attr.family = "IPQ";
|
||||
qs->attr.machine = socinfo_machine(&pdev->dev,
|
||||
le32_to_cpu(info->id));
|
||||
qs->attr.soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u",
|
||||
@@ -772,6 +774,9 @@ static int qcom_socinfo_probe(struct pla
|
||||
if (IS_ERR(qs->soc_dev))
|
||||
return PTR_ERR(qs->soc_dev);
|
||||
|
||||
+ pr_info("CPU: %s, SoC Version: %s id: %d fmt: %x\n", qs->attr.machine,
|
||||
+ qs->attr.revision, info->id, qs->info.fmt);
|
||||
+
|
||||
socinfo_debugfs_init(qs, info, item_size);
|
||||
|
||||
/* Feed the soc specific unique data into entropy pool */
|
||||
@@ -0,0 +1,38 @@
|
||||
From a6c62be5177cf3b383188a79241bd6d5833173d0 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Mon, 6 Apr 2020 11:08:09 -0700
|
||||
Subject: [PATCH 243/281] netfilter: export udp_get_timeouts function
|
||||
|
||||
This function is required for acceleration support.
|
||||
|
||||
Change-Id: Ibca4f402735764e7e6fb3ce2678e670753c6ef9c
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
include/net/netfilter/nf_conntrack_timeout.h | 1 +
|
||||
net/netfilter/nf_conntrack_proto_udp.c | 3 ++-
|
||||
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/net/netfilter/nf_conntrack_timeout.h
|
||||
+++ b/include/net/netfilter/nf_conntrack_timeout.h
|
||||
@@ -107,5 +107,6 @@ struct nf_ct_timeout_hooks {
|
||||
|
||||
extern const struct nf_ct_timeout_hooks __rcu *nf_ct_timeout_hook;
|
||||
#endif
|
||||
+extern unsigned int *udp_get_timeouts(struct net *net);
|
||||
|
||||
#endif /* _NF_CONNTRACK_TIMEOUT_H */
|
||||
--- a/net/netfilter/nf_conntrack_proto_udp.c
|
||||
+++ b/net/netfilter/nf_conntrack_proto_udp.c
|
||||
@@ -29,10 +29,11 @@ static const unsigned int udp_timeouts[U
|
||||
[UDP_CT_REPLIED] = 120*HZ,
|
||||
};
|
||||
|
||||
-static unsigned int *udp_get_timeouts(struct net *net)
|
||||
+unsigned int *udp_get_timeouts(struct net *net)
|
||||
{
|
||||
return nf_udp_pernet(net)->timeouts;
|
||||
}
|
||||
+EXPORT_SYMBOL(udp_get_timeouts);
|
||||
|
||||
static void udp_error_log(const struct sk_buff *skb,
|
||||
const struct nf_hook_state *state,
|
||||
@@ -0,0 +1,38 @@
|
||||
From fc86132bb4893d1747dc2c652a9ad722096dd4f8 Mon Sep 17 00:00:00 2001
|
||||
From: Zhu Ken <guigenz@codeaurora.org>
|
||||
Date: Wed, 14 Jun 2017 11:45:28 -0700
|
||||
Subject: [PATCH 244/281] bridge: fix eapol packet dropping issue
|
||||
|
||||
wpa_supplicant would receive EAPOL packet to start 802.1x session even if
|
||||
its wireless STA interface enslaved in a bridge is disabled.
|
||||
|
||||
Change-Id: I4e3f786049a19c5bc7aacdc0528b0099744e8674
|
||||
Signed-off-by: Zhu Ken <guigenz@codeaurora.org>
|
||||
---
|
||||
net/bridge/br_input.c | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -451,13 +451,15 @@ forward:
|
||||
|
||||
switch (p->state) {
|
||||
case BR_STATE_DISABLED:
|
||||
- if (ether_addr_equal(p->br->dev->dev_addr, dest))
|
||||
- skb->pkt_type = PACKET_HOST;
|
||||
+ if (skb->protocol == htons(ETH_P_PAE)) {
|
||||
+ if (ether_addr_equal(p->br->dev->dev_addr, dest))
|
||||
+ skb->pkt_type = PACKET_HOST;
|
||||
|
||||
- if (BR_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING,
|
||||
- dev_net(skb->dev), NULL, skb, skb->dev, NULL,
|
||||
- br_handle_local_finish) == 1) {
|
||||
- return RX_HANDLER_PASS;
|
||||
+ if (BR_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING,
|
||||
+ dev_net(skb->dev), NULL, skb, skb->dev, NULL,
|
||||
+ br_handle_local_finish) == 1) {
|
||||
+ return RX_HANDLER_PASS;
|
||||
+ }
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
From a3b1392df5e6480db14e9036cbe57f6f9b762d5a Mon Sep 17 00:00:00 2001
|
||||
From: Varsha Mishra <varsham@codeaurora.org>
|
||||
Date: Thu, 11 Jun 2020 18:45:40 +0530
|
||||
Subject: [PATCH 245/281] bridge: Get hairpin enabled information from bridge.
|
||||
|
||||
Add API to let other modules find out if bridge has
|
||||
hairpin enabled or not.
|
||||
Change-Id: I04c76345111bf8297dbe41230e1254df33556d52
|
||||
Signed-off-by: Varsha Mishra <varsham@codeaurora.org>
|
||||
---
|
||||
include/linux/if_bridge.h | 1 +
|
||||
net/bridge/br_if.c | 11 +++++++++++
|
||||
2 files changed, 12 insertions(+)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -85,6 +85,7 @@ extern struct net_bridge_fdb_entry *br_f
|
||||
__u16 vid);
|
||||
extern void br_fdb_update_register_notify(struct notifier_block *nb);
|
||||
extern void br_fdb_update_unregister_notify(struct notifier_block *nb);
|
||||
+extern bool br_is_hairpin_enabled(struct net_device *dev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
|
||||
int br_multicast_list_adjacent(struct net_device *dev,
|
||||
--- a/net/bridge/br_if.c
|
||||
+++ b/net/bridge/br_if.c
|
||||
@@ -866,3 +866,14 @@ void br_dev_update_stats(struct net_devi
|
||||
local_bh_enable();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(br_dev_update_stats);
|
||||
+
|
||||
+/* API to know if hairpin feature is enabled/disabled on this bridge port */
|
||||
+bool br_is_hairpin_enabled(struct net_device *dev)
|
||||
+{
|
||||
+ struct net_bridge_port *port = br_port_get_check_rcu(dev);
|
||||
+
|
||||
+ if (likely(port))
|
||||
+ return port->flags & BR_HAIRPIN_MODE;
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_is_hairpin_enabled);
|
||||
@@ -0,0 +1,87 @@
|
||||
From ce18a6fdff6a39a01111d74f513d2ef66142047c Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <msezgin@codeaurora.org>
|
||||
Date: Wed, 5 Aug 2020 13:21:27 -0700
|
||||
Subject: [PATCH 246/281] net:ipv6: Fix IPv6 user route change event calls
|
||||
|
||||
These events should be called only when the route table is
|
||||
changed by the userspace. So, we should call them in the
|
||||
ioctl and the netlink message handler function.
|
||||
|
||||
Change-Id: If7ec615014cfc79d5fa72878e49eaf99c2560c32
|
||||
Signed-off-by: Murat Sezgin <msezgin@codeaurora.org>
|
||||
---
|
||||
net/ipv6/route.c | 31 +++++++++++++++++++++----------
|
||||
1 file changed, 21 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/net/ipv6/route.c
|
||||
+++ b/net/ipv6/route.c
|
||||
@@ -3876,9 +3876,6 @@ int ip6_route_add(struct fib6_config *cf
|
||||
return PTR_ERR(rt);
|
||||
|
||||
err = __ip6_ins_rt(rt, &cfg->fc_nlinfo, extack);
|
||||
- if (!err)
|
||||
- atomic_notifier_call_chain(&ip6route_chain,
|
||||
- RTM_NEWROUTE, rt);
|
||||
fib6_info_release(rt);
|
||||
|
||||
return err;
|
||||
@@ -3899,9 +3896,7 @@ static int __ip6_del_rt(struct fib6_info
|
||||
spin_lock_bh(&table->tb6_lock);
|
||||
err = fib6_del(rt, info);
|
||||
spin_unlock_bh(&table->tb6_lock);
|
||||
- if (!err)
|
||||
- atomic_notifier_call_chain(&ip6route_chain,
|
||||
- RTM_DELROUTE, rt);
|
||||
+
|
||||
out:
|
||||
fib6_info_release(rt);
|
||||
return err;
|
||||
@@ -4510,6 +4505,10 @@ int ipv6_route_ioctl(struct net *net, un
|
||||
break;
|
||||
}
|
||||
rtnl_unlock();
|
||||
+ if (!err)
|
||||
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||
+ (cmd == SIOCADDRT) ? RTM_NEWROUTE : RTM_DELROUTE, &cfg);
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -5532,11 +5531,17 @@ static int inet6_rtm_delroute(struct sk_
|
||||
}
|
||||
|
||||
if (cfg.fc_mp)
|
||||
- return ip6_route_multipath_del(&cfg, extack);
|
||||
+ err = ip6_route_multipath_del(&cfg, extack);
|
||||
else {
|
||||
cfg.fc_delete_all_nh = 1;
|
||||
- return ip6_route_del(&cfg, extack);
|
||||
+ err = ip6_route_del(&cfg, extack);
|
||||
}
|
||||
+
|
||||
+ if (!err)
|
||||
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||
+ RTM_DELROUTE, &cfg);
|
||||
+
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
@@ -5553,9 +5558,15 @@ static int inet6_rtm_newroute(struct sk_
|
||||
cfg.fc_metric = IP6_RT_PRIO_USER;
|
||||
|
||||
if (cfg.fc_mp)
|
||||
- return ip6_route_multipath_add(&cfg, extack);
|
||||
+ err = ip6_route_multipath_add(&cfg, extack);
|
||||
else
|
||||
- return ip6_route_add(&cfg, GFP_KERNEL, extack);
|
||||
+ err = ip6_route_add(&cfg, GFP_KERNEL, extack);
|
||||
+
|
||||
+ if (!err)
|
||||
+ atomic_notifier_call_chain(&ip6route_chain,
|
||||
+ RTM_NEWROUTE, &cfg);
|
||||
+
|
||||
+ return err;
|
||||
}
|
||||
|
||||
/* add the overhead of this fib6_nh to nexthop_len */
|
||||
@@ -0,0 +1,24 @@
|
||||
From 38749dbfcfb8b471b9eea391729b9a2a1f215bf2 Mon Sep 17 00:00:00 2001
|
||||
From: Tian Yang <tiany@codeaurora.org>
|
||||
Date: Wed, 9 Sep 2020 15:11:58 -0700
|
||||
Subject: [PATCH 247/281] net_bridge: Export br_fdb_find_rcu symbol
|
||||
|
||||
Export br_fdb_find_rcu symbol to be used for other module
|
||||
to find fdb entry.
|
||||
|
||||
Change-Id: I3df88b35ddfad2d295cdd45303002c5db015ff8c
|
||||
Signed-off-by: Tian Yang <tiany@codeaurora.org>
|
||||
---
|
||||
net/bridge/br_fdb.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -305,6 +305,7 @@ struct net_bridge_fdb_entry *br_fdb_find
|
||||
{
|
||||
return fdb_find_rcu(&br->fdb_hash_tbl, addr, vid);
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_find_rcu);
|
||||
|
||||
/* When a static FDB entry is added, the mac address from the entry is
|
||||
* added to the bridge private HW address list and all required ports
|
||||
@@ -0,0 +1,35 @@
|
||||
From 0564884785c2f49419b8d14ca98141c8e85cd8ab Mon Sep 17 00:00:00 2001
|
||||
From: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
|
||||
Date: Thu, 17 Mar 2016 10:57:38 -0600
|
||||
Subject: [PATCH 251/281] net: core: neighbour: Change the print format for
|
||||
addresses
|
||||
|
||||
Print format %p displays the kernel address while bypassing the
|
||||
kptr_restrict sysctl settings.
|
||||
|
||||
Change the print format for addresses from %p to %pK. If
|
||||
kptr_restrict is enabled, addresses are printed as zeroes. To view
|
||||
the actual addresses, disable kptr_restrict by -
|
||||
echo 0 > /proc/sys/kernel/kptr_restrict
|
||||
|
||||
This patch applies the vollowing change from kernel/msm-3.18:
|
||||
ee833ce586 (net: core: neighbour: Change the print format for addresses)
|
||||
|
||||
CRs-Fixed: 987041
|
||||
Change-Id: I2eb33c63168ab26818dfdb3e11315f2ce8f24fa5
|
||||
Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
|
||||
---
|
||||
net/core/neighbour.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/net/core/neighbour.c
|
||||
+++ b/net/core/neighbour.c
|
||||
@@ -893,7 +893,7 @@ void neigh_destroy(struct neighbour *nei
|
||||
NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
|
||||
|
||||
if (!neigh->dead) {
|
||||
- pr_warn("Destroying alive neighbour %p\n", neigh);
|
||||
+ pr_warn("Destroying alive neighbour %pK\n", neigh);
|
||||
dump_stack();
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
From 96ab6b43388743ebc70a0b40290f6f5655e3c33f Mon Sep 17 00:00:00 2001
|
||||
From: Suman Ghosh <sumaghos@codeaurora.org>
|
||||
Date: Thu, 10 Dec 2020 00:11:41 +0530
|
||||
Subject: [PATCH] net: macvlan: Add statistics update function for macvlan net
|
||||
device.
|
||||
|
||||
Signed-off-by: Suman Ghosh <sumaghos@codeaurora.org>
|
||||
Change-Id: I9cd995f9d1c0f85c61781a8af845b4dbb86bebd0
|
||||
|
||||
net: macvlan: Avoid updating error and drop counters for offloaded statistics.
|
||||
|
||||
Signed-off-by: Suman Ghosh <sumaghos@codeaurora.org>
|
||||
Change-Id: Ibb7f3f5a0e73cda140adee2c1640af03c698f6e6
|
||||
---
|
||||
drivers/net/macvlan.c | 27 +++++++++++++++++++++++++++
|
||||
include/linux/if_macvlan.h | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 51 insertions(+)
|
||||
|
||||
--- a/drivers/net/macvlan.c
|
||||
+++ b/drivers/net/macvlan.c
|
||||
@@ -960,6 +960,32 @@ static void macvlan_uninit(struct net_de
|
||||
macvlan_port_destroy(port->dev);
|
||||
}
|
||||
|
||||
+/* Update macvlan statistics processed by offload engines */
|
||||
+static void macvlan_dev_update_stats(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *offl_stats,
|
||||
+ bool update_mcast_rx_stats)
|
||||
+{
|
||||
+ struct vlan_pcpu_stats *stats;
|
||||
+ struct macvlan_dev *macvlan;
|
||||
+
|
||||
+ /* Is this a macvlan? */
|
||||
+ if (!netif_is_macvlan(dev))
|
||||
+ return;
|
||||
+
|
||||
+ macvlan = netdev_priv(dev);
|
||||
+ stats = this_cpu_ptr(macvlan->pcpu_stats);
|
||||
+ u64_stats_update_begin(&stats->syncp);
|
||||
+ u64_stats_add(&stats->rx_packets, offl_stats->rx_packets);
|
||||
+ u64_stats_add(&stats->rx_bytes, offl_stats->rx_bytes);
|
||||
+ u64_stats_add(&stats->tx_packets, offl_stats->tx_packets);
|
||||
+ u64_stats_add(&stats->tx_bytes, offl_stats->tx_bytes);
|
||||
+ /* Update multicast statistics */
|
||||
+ if (unlikely(update_mcast_rx_stats)) {
|
||||
+ u64_stats_add(&stats->rx_multicast, offl_stats->rx_packets);
|
||||
+ }
|
||||
+ u64_stats_update_end(&stats->syncp);
|
||||
+}
|
||||
+
|
||||
static void macvlan_dev_get_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
@@ -1506,6 +1532,7 @@ int macvlan_common_newlink(struct net *s
|
||||
vlan->dev = dev;
|
||||
vlan->port = port;
|
||||
vlan->set_features = MACVLAN_FEATURES;
|
||||
+ vlan->offload_stats_update = macvlan_dev_update_stats;
|
||||
|
||||
vlan->mode = MACVLAN_MODE_VEPA;
|
||||
if (data && data[IFLA_MACVLAN_MODE])
|
||||
--- a/include/linux/if_macvlan.h
|
||||
+++ b/include/linux/if_macvlan.h
|
||||
@@ -15,6 +15,11 @@ struct macvlan_port;
|
||||
#define MACVLAN_MC_FILTER_BITS 8
|
||||
#define MACVLAN_MC_FILTER_SZ (1 << MACVLAN_MC_FILTER_BITS)
|
||||
|
||||
+/*
|
||||
+ * Callback for updating interface statistics for macvlan flows offloaded from host CPU.
|
||||
+ */
|
||||
+typedef void (*macvlan_offload_stats_update_cb_t)(struct net_device *dev, struct rtnl_link_stats64 *stats, bool update_mcast_rx_stats);
|
||||
+
|
||||
struct macvlan_dev {
|
||||
struct net_device *dev;
|
||||
struct list_head list;
|
||||
@@ -35,6 +40,7 @@ struct macvlan_dev {
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
struct netpoll *netpoll;
|
||||
#endif
|
||||
+ macvlan_offload_stats_update_cb_t offload_stats_update;
|
||||
};
|
||||
|
||||
static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
|
||||
@@ -68,6 +74,24 @@ extern void macvlan_dellink(struct net_d
|
||||
extern int macvlan_link_register(struct rtnl_link_ops *ops);
|
||||
|
||||
#if IS_ENABLED(CONFIG_MACVLAN)
|
||||
+static inline void
|
||||
+macvlan_offload_stats_update(struct net_device *dev,
|
||||
+ struct rtnl_link_stats64 *stats,
|
||||
+ bool update_mcast_rx_stats)
|
||||
+{
|
||||
+ struct macvlan_dev *macvlan = netdev_priv(dev);
|
||||
+
|
||||
+ macvlan->offload_stats_update(dev, stats, update_mcast_rx_stats);
|
||||
+}
|
||||
+
|
||||
+static inline enum
|
||||
+macvlan_mode macvlan_get_mode(struct net_device *dev)
|
||||
+{
|
||||
+ struct macvlan_dev *macvlan = netdev_priv(dev);
|
||||
+
|
||||
+ return macvlan->mode;
|
||||
+}
|
||||
+
|
||||
static inline struct net_device *
|
||||
macvlan_dev_real_dev(const struct net_device *dev)
|
||||
{
|
||||
@@ -0,0 +1,77 @@
|
||||
--- a/include/net/ip6_tunnel.h
|
||||
+++ b/include/net/ip6_tunnel.h
|
||||
@@ -36,6 +36,7 @@ struct __ip6_tnl_parm {
|
||||
__u8 proto; /* tunnel protocol */
|
||||
__u8 encap_limit; /* encapsulation limit for tunnel */
|
||||
__u8 hop_limit; /* hop limit for tunnel */
|
||||
+ __u8 draft03; /* FMR using draft03 of map-e - QCA NSS Clients Support */
|
||||
bool collect_md;
|
||||
__be32 flowinfo; /* traffic class and flowlabel for tunnel */
|
||||
__u32 flags; /* tunnel flags */
|
||||
--- a/include/net/ip_tunnels.h
|
||||
+++ b/include/net/ip_tunnels.h
|
||||
@@ -592,4 +592,9 @@ static inline void ip_tunnel_info_opts_s
|
||||
|
||||
#endif /* CONFIG_INET */
|
||||
|
||||
+/* QCA NSS Clients Support - Start */
|
||||
+void ipip6_update_offload_stats(struct net_device *dev, void *ptr);
|
||||
+void ip6_update_offload_stats(struct net_device *dev, void *ptr);
|
||||
+/* QCA NSS Clients Support - End */
|
||||
+
|
||||
#endif /* __NET_IP_TUNNELS_H */
|
||||
--- a/net/ipv6/ip6_tunnel.c
|
||||
+++ b/net/ipv6/ip6_tunnel.c
|
||||
@@ -2414,6 +2414,26 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
+/* QCA NSS Client Support - Start */
|
||||
+/*
|
||||
+ * Update offload stats
|
||||
+ */
|
||||
+void ip6_update_offload_stats(struct net_device *dev, void *ptr)
|
||||
+{
|
||||
+ struct pcpu_sw_netstats *tstats = per_cpu_ptr(dev->tstats, 0);
|
||||
+ const struct pcpu_sw_netstats *offload_stats =
|
||||
+ (struct pcpu_sw_netstats *)ptr;
|
||||
+
|
||||
+ u64_stats_update_begin(&tstats->syncp);
|
||||
+ u64_stats_add(&tstats->tx_packets, u64_stats_read(&offload_stats->tx_packets));
|
||||
+ u64_stats_add(&tstats->tx_bytes, u64_stats_read(&offload_stats->tx_bytes));
|
||||
+ u64_stats_add(&tstats->rx_packets, u64_stats_read(&offload_stats->rx_packets));
|
||||
+ u64_stats_add(&tstats->rx_bytes, u64_stats_read(&offload_stats->rx_bytes));
|
||||
+ u64_stats_update_end(&tstats->syncp);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ip6_update_offload_stats);
|
||||
+/* QCA NSS Client Support - End */
|
||||
+
|
||||
struct net *ip6_tnl_get_link_net(const struct net_device *dev)
|
||||
{
|
||||
struct ip6_tnl *tunnel = netdev_priv(dev);
|
||||
--- a/net/ipv6/sit.c
|
||||
+++ b/net/ipv6/sit.c
|
||||
@@ -1734,6 +1734,23 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
+/* QCA NSS Clients Support - Start */
|
||||
+void ipip6_update_offload_stats(struct net_device *dev, void *ptr)
|
||||
+{
|
||||
+ struct pcpu_sw_netstats *tstats = per_cpu_ptr(dev->tstats, 0);
|
||||
+ const struct pcpu_sw_netstats *offload_stats =
|
||||
+ (struct pcpu_sw_netstats *)ptr;
|
||||
+
|
||||
+ u64_stats_update_begin(&tstats->syncp);
|
||||
+ u64_stats_add(&tstats->tx_packets, u64_stats_read(&offload_stats->tx_packets));
|
||||
+ u64_stats_add(&tstats->tx_bytes, u64_stats_read(&offload_stats->tx_bytes));
|
||||
+ u64_stats_add(&tstats->rx_packets, u64_stats_read(&offload_stats->rx_packets));
|
||||
+ u64_stats_add(&tstats->rx_bytes, u64_stats_read(&offload_stats->rx_bytes));
|
||||
+ u64_stats_update_end(&tstats->syncp);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ipip6_update_offload_stats);
|
||||
+/* QCA NSS Clients Support - End */
|
||||
+
|
||||
static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NLA_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
|
||||
@@ -0,0 +1,132 @@
|
||||
From 3fda44006f8cbca0670305f6543c223f8e6a0243 Mon Sep 17 00:00:00 2001
|
||||
From: Vishnu Vardhan Bantanahal <quic_vishvard@quicinc.com>
|
||||
Date: Thu, 1 Jun 2023 17:23:35 +0530
|
||||
Subject: [PATCH] net: vxlan: Adding APIs to VxLAN driver.
|
||||
|
||||
Adding new APIs to verify VxLAN netdevice and
|
||||
update mac entries in VxLAN's fdb.
|
||||
Change-Id: I22962d4845cba3a258c095f6424557a29d3b354b
|
||||
Signed-off-by: Apoorv Gupta <apoogupt@codeaurora.org>
|
||||
|
||||
net: vxlan: Added vxlan fdb notify chain
|
||||
|
||||
Registered modules are notified based on following events:
|
||||
1. RTM_GETNEIGH
|
||||
2. RTM_NEWNEIGH
|
||||
3. RTM_DELNEIGH
|
||||
|
||||
Change-Id: I0802b305a829800cafbabd4728c3c47ff3679938
|
||||
Signed-off-by: Cemil Coskun <ccoskun@codeaurora.org>
|
||||
Signed-off-by: Apoorv Gupta <apoogupt@codeaurora.org>
|
||||
Signed-off-by: Vishnu Vardhan Bantanahal <quic_vishvard@quicinc.com>
|
||||
---
|
||||
drivers/net/vxlan/vxlan_core.c | 31 +++++++++++++++++++++++++++++++
|
||||
include/net/vxlan.h | 29 +++++++++++++++++++++++++++++
|
||||
2 files changed, 60 insertions(+)
|
||||
|
||||
--- a/drivers/net/vxlan/vxlan_core.c
|
||||
+++ b/drivers/net/vxlan/vxlan_core.c
|
||||
@@ -65,6 +65,20 @@ static void vxlan_vs_del_dev(struct vxla
|
||||
/* salt for hash table */
|
||||
static u32 vxlan_salt __read_mostly;
|
||||
|
||||
+ATOMIC_NOTIFIER_HEAD(vxlan_fdb_notifier_list);
|
||||
+
|
||||
+void vxlan_fdb_register_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_register(&vxlan_fdb_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL(vxlan_fdb_register_notify);
|
||||
+
|
||||
+void vxlan_fdb_unregister_notify(struct notifier_block *nb)
|
||||
+{
|
||||
+ atomic_notifier_chain_unregister(&vxlan_fdb_notifier_list, nb);
|
||||
+}
|
||||
+EXPORT_SYMBOL(vxlan_fdb_unregister_notify);
|
||||
+
|
||||
static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
|
||||
{
|
||||
return vs->flags & VXLAN_F_COLLECT_METADATA ||
|
||||
@@ -260,6 +274,7 @@ static void __vxlan_fdb_notify(struct vx
|
||||
{
|
||||
struct net *net = dev_net(vxlan->dev);
|
||||
struct sk_buff *skb;
|
||||
+ struct vxlan_fdb_event vfe;
|
||||
int err = -ENOBUFS;
|
||||
|
||||
skb = nlmsg_new(vxlan_nlmsg_size(), GFP_ATOMIC);
|
||||
@@ -275,6 +290,10 @@ static void __vxlan_fdb_notify(struct vx
|
||||
}
|
||||
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
|
||||
+ vfe.dev = vxlan->dev;
|
||||
+ vfe.rdst = rd;
|
||||
+ ether_addr_copy(vfe.eth_addr, fdb->eth_addr);
|
||||
+ atomic_notifier_call_chain(&vxlan_fdb_notifier_list, type, (void *)&vfe);
|
||||
return;
|
||||
errout:
|
||||
if (err < 0)
|
||||
@@ -441,6 +460,18 @@ static struct vxlan_fdb *vxlan_find_mac(
|
||||
return f;
|
||||
}
|
||||
|
||||
+/* Find and update age of fdb entry corresponding to MAC. */
|
||||
+void vxlan_fdb_update_mac(struct vxlan_dev *vxlan, const u8 *mac, uint32_t vni)
|
||||
+{
|
||||
+ u32 hash_index;
|
||||
+
|
||||
+ hash_index = fdb_head_index(vxlan, mac, vni);
|
||||
+ spin_lock_bh(&vxlan->hash_lock[hash_index]);
|
||||
+ vxlan_find_mac(vxlan, mac, vni);
|
||||
+ spin_unlock_bh(&vxlan->hash_lock[hash_index]);
|
||||
+}
|
||||
+EXPORT_SYMBOL(vxlan_fdb_update_mac);
|
||||
+
|
||||
/* caller should hold vxlan->hash_lock */
|
||||
static struct vxlan_rdst *vxlan_fdb_find_rdst(struct vxlan_fdb *f,
|
||||
union vxlan_addr *ip, __be16 port,
|
||||
--- a/include/net/vxlan.h
|
||||
+++ b/include/net/vxlan.h
|
||||
@@ -352,6 +352,19 @@ struct vxlan_dev {
|
||||
VXLAN_F_VNIFILTER | \
|
||||
VXLAN_F_LOCALBYPASS)
|
||||
|
||||
+/*
|
||||
+ * Application data for fdb notifier event
|
||||
+ */
|
||||
+struct vxlan_fdb_event {
|
||||
+ struct net_device *dev;
|
||||
+ struct vxlan_rdst *rdst;
|
||||
+ u8 eth_addr[ETH_ALEN];
|
||||
+};
|
||||
+
|
||||
+extern void vxlan_fdb_register_notify(struct notifier_block *nb);
|
||||
+extern void vxlan_fdb_unregister_notify(struct notifier_block *nb);
|
||||
+extern void vxlan_fdb_update_mac(struct vxlan_dev *vxlan, const u8 *mac, uint32_t vni);
|
||||
+
|
||||
struct net_device *vxlan_dev_create(struct net *net, const char *name,
|
||||
u8 name_assign_type, struct vxlan_config *conf);
|
||||
|
||||
@@ -440,6 +453,22 @@ static inline __be32 vxlan_compute_rco(u
|
||||
return vni_field;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * is_vxlan_dev()
|
||||
+ * Check if it is a VxLAN netdevice.
|
||||
+ */
|
||||
+static inline bool is_vxlan_dev(const struct net_device *dev)
|
||||
+{
|
||||
+ if (!dev)
|
||||
+ return false;
|
||||
+
|
||||
+ if ((dev->dev.type) &&
|
||||
+ !strncmp(dev->dev.type->name, "vxlan", sizeof("vxlan"))) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)
|
||||
{
|
||||
return vs->sock->sk->sk_family;
|
||||
@@ -0,0 +1,111 @@
|
||||
--- a/crypto/authenc.c
|
||||
+++ b/crypto/authenc.c
|
||||
@@ -415,6 +415,8 @@ static int crypto_authenc_create(struct
|
||||
enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
|
||||
goto err_free_inst;
|
||||
|
||||
+ inst->alg.base.cra_flags |= (auth_base->cra_flags |
|
||||
+ enc->base.cra_flags) & CRYPTO_ALG_NOSUPP_SG;
|
||||
inst->alg.base.cra_priority = enc->base.cra_priority * 10 +
|
||||
auth_base->cra_priority;
|
||||
inst->alg.base.cra_blocksize = enc->base.cra_blocksize;
|
||||
--- a/include/linux/crypto.h
|
||||
+++ b/include/linux/crypto.h
|
||||
@@ -86,6 +86,11 @@
|
||||
#define CRYPTO_NOLOAD 0x00008000
|
||||
|
||||
/*
|
||||
+ * Set this flag if algorithm does not support SG list transforms
|
||||
+ */
|
||||
+#define CRYPTO_ALG_NOSUPP_SG 0x0000c000
|
||||
+
|
||||
+/*
|
||||
* The algorithm may allocate memory during request processing, i.e. during
|
||||
* encryption, decryption, or hashing. Users can request an algorithm with this
|
||||
* flag unset if they can't handle memory allocation failures.
|
||||
--- a/net/ipv4/esp4.c
|
||||
+++ b/net/ipv4/esp4.c
|
||||
@@ -657,6 +657,7 @@ static int esp_output(struct xfrm_state
|
||||
struct ip_esp_hdr *esph;
|
||||
struct crypto_aead *aead;
|
||||
struct esp_info esp;
|
||||
+ bool nosupp_sg;
|
||||
|
||||
esp.inplace = true;
|
||||
|
||||
@@ -668,6 +669,11 @@ static int esp_output(struct xfrm_state
|
||||
aead = x->data;
|
||||
alen = crypto_aead_authsize(aead);
|
||||
|
||||
+ nosupp_sg = crypto_tfm_alg_type(&aead->base) & CRYPTO_ALG_NOSUPP_SG;
|
||||
+ if (nosupp_sg && skb_linearize(skb)) {
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
esp.tfclen = 0;
|
||||
if (x->tfcpad) {
|
||||
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
|
||||
@@ -889,6 +895,7 @@ static int esp_input(struct xfrm_state *
|
||||
u8 *iv;
|
||||
struct scatterlist *sg;
|
||||
int err = -EINVAL;
|
||||
+ bool nosupp_sg;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + ivlen))
|
||||
goto out;
|
||||
@@ -896,6 +903,12 @@ static int esp_input(struct xfrm_state *
|
||||
if (elen <= 0)
|
||||
goto out;
|
||||
|
||||
+ nosupp_sg = crypto_tfm_alg_type(&aead->base) & CRYPTO_ALG_NOSUPP_SG;
|
||||
+ if (nosupp_sg && skb_linearize(skb)) {
|
||||
+ err = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
assoclen = sizeof(struct ip_esp_hdr);
|
||||
seqhilen = 0;
|
||||
|
||||
--- a/net/ipv6/esp6.c
|
||||
+++ b/net/ipv6/esp6.c
|
||||
@@ -695,6 +695,7 @@ static int esp6_output(struct xfrm_state
|
||||
struct ip_esp_hdr *esph;
|
||||
struct crypto_aead *aead;
|
||||
struct esp_info esp;
|
||||
+ bool nosupp_sg;
|
||||
|
||||
esp.inplace = true;
|
||||
|
||||
@@ -706,6 +707,11 @@ static int esp6_output(struct xfrm_state
|
||||
aead = x->data;
|
||||
alen = crypto_aead_authsize(aead);
|
||||
|
||||
+ nosupp_sg = crypto_tfm_alg_type(&aead->base) & CRYPTO_ALG_NOSUPP_SG;
|
||||
+ if (nosupp_sg && skb_linearize(skb)) {
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
esp.tfclen = 0;
|
||||
if (x->tfcpad) {
|
||||
struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
|
||||
@@ -933,6 +939,7 @@ static int esp6_input(struct xfrm_state
|
||||
__be32 *seqhi;
|
||||
u8 *iv;
|
||||
struct scatterlist *sg;
|
||||
+ bool nosupp_sg;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr) + ivlen)) {
|
||||
ret = -EINVAL;
|
||||
@@ -944,6 +951,12 @@ static int esp6_input(struct xfrm_state
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ nosupp_sg = crypto_tfm_alg_type(&aead->base) & CRYPTO_ALG_NOSUPP_SG;
|
||||
+ if (nosupp_sg && skb_linearize(skb)) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
assoclen = sizeof(struct ip_esp_hdr);
|
||||
seqhilen = 0;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
From ed42112c77bfb68594f49e252ace2dd6b8c8e7ff Mon Sep 17 00:00:00 2001
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Thu, 16 Mar 2023 17:21:39 +0530
|
||||
Subject: [PATCH 063/281] OpenWrt:
|
||||
613-netfilter_optional_tcp_window_check.patch
|
||||
|
||||
netfilter: optional tcp window check
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
|
||||
|
||||
Change-Id: I6f7a23b89062cca58c87554e75ae32b0e2aa2831
|
||||
Signed-off-by: Ram Chandra Jangir <quic_rjangir@quicinc.com>
|
||||
---
|
||||
include/net/netns/conntrack.h | 1 +
|
||||
net/netfilter/nf_conntrack_proto_tcp.c | 9 ++++++++-
|
||||
net/netfilter/nf_conntrack_standalone.c | 10 ++++++++++
|
||||
3 files changed, 19 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/include/net/netns/conntrack.h
|
||||
+++ b/include/net/netns/conntrack.h
|
||||
@@ -26,6 +26,7 @@ struct nf_tcp_net {
|
||||
unsigned int timeouts[TCP_CONNTRACK_TIMEOUT_MAX];
|
||||
u8 tcp_loose;
|
||||
u8 tcp_be_liberal;
|
||||
+ u8 tcp_no_window_check;
|
||||
u8 tcp_max_retrans;
|
||||
u8 tcp_ignore_invalid_rst;
|
||||
#if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
|
||||
--- a/net/netfilter/nf_conntrack_proto_tcp.c
|
||||
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
|
||||
@@ -515,11 +515,15 @@ tcp_in_window(struct nf_conn *ct, enum i
|
||||
struct ip_ct_tcp *state = &ct->proto.tcp;
|
||||
struct ip_ct_tcp_state *sender = &state->seen[dir];
|
||||
struct ip_ct_tcp_state *receiver = &state->seen[!dir];
|
||||
+ const struct nf_tcp_net *tn = nf_tcp_pernet(nf_ct_net(ct));
|
||||
__u32 seq, ack, sack, end, win, swin;
|
||||
bool in_recv_win, seq_ok;
|
||||
s32 receiver_offset;
|
||||
u16 win_raw;
|
||||
|
||||
+ if (tn->tcp_no_window_check)
|
||||
+ return NFCT_TCP_ACCEPT;
|
||||
+
|
||||
/*
|
||||
* Get the required data from the packet.
|
||||
*/
|
||||
@@ -1285,7 +1289,7 @@ int nf_conntrack_tcp_packet(struct nf_co
|
||||
IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
|
||||
timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
|
||||
timeout = timeouts[TCP_CONNTRACK_UNACK];
|
||||
- else if (ct->proto.tcp.last_win == 0 &&
|
||||
+ else if (!tn->tcp_no_window_check && ct->proto.tcp.last_win == 0 &&
|
||||
timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
|
||||
timeout = timeouts[TCP_CONNTRACK_RETRANS];
|
||||
else
|
||||
@@ -1601,6 +1605,9 @@ void nf_conntrack_tcp_init_net(struct ne
|
||||
*/
|
||||
tn->tcp_be_liberal = 0;
|
||||
|
||||
+ /* Skip Windows Check */
|
||||
+ tn->tcp_no_window_check = 0;
|
||||
+
|
||||
/* If it's non-zero, we turn off RST sequence number check */
|
||||
tn->tcp_ignore_invalid_rst = 0;
|
||||
|
||||
--- a/net/netfilter/nf_conntrack_standalone.c
|
||||
+++ b/net/netfilter/nf_conntrack_standalone.c
|
||||
@@ -630,6 +630,7 @@ enum nf_ct_sysctl_index {
|
||||
#endif
|
||||
NF_SYSCTL_CT_PROTO_TCP_LOOSE,
|
||||
NF_SYSCTL_CT_PROTO_TCP_LIBERAL,
|
||||
+ NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK,
|
||||
NF_SYSCTL_CT_PROTO_TCP_IGNORE_INVALID_RST,
|
||||
NF_SYSCTL_CT_PROTO_TCP_MAX_RETRANS,
|
||||
NF_SYSCTL_CT_PROTO_TIMEOUT_UDP,
|
||||
@@ -834,6 +835,14 @@ static struct ctl_table nf_ct_sysctl_tab
|
||||
.extra1 = SYSCTL_ZERO,
|
||||
.extra2 = SYSCTL_ONE,
|
||||
},
|
||||
+ [NF_SYSCTL_CT_PROTO_TCP_NO_WINDOW_CHECK] = {
|
||||
+ .procname = "nf_conntrack_tcp_no_window_check",
|
||||
+ .maxlen = sizeof(u8),
|
||||
+ .mode = 0644,
|
||||
+ .proc_handler = proc_dou8vec_minmax,
|
||||
+ .extra1 = SYSCTL_ZERO,
|
||||
+ .extra2 = SYSCTL_ONE,
|
||||
+ },
|
||||
[NF_SYSCTL_CT_PROTO_TCP_IGNORE_INVALID_RST] = {
|
||||
.procname = "nf_conntrack_tcp_ignore_invalid_rst",
|
||||
.maxlen = sizeof(u8),
|
||||
@@ -1035,6 +1044,7 @@ static void nf_conntrack_standalone_init
|
||||
|
||||
XASSIGN(LOOSE, &tn->tcp_loose);
|
||||
XASSIGN(LIBERAL, &tn->tcp_be_liberal);
|
||||
+ XASSIGN(NO_WINDOW_CHECK, &tn->tcp_no_window_check);
|
||||
XASSIGN(MAX_RETRANS, &tn->tcp_max_retrans);
|
||||
XASSIGN(IGNORE_INVALID_RST, &tn->tcp_ignore_invalid_rst);
|
||||
#undef XASSIGN
|
||||
@@ -0,0 +1,44 @@
|
||||
From 4746722090513b5ad66819a758004ac198ccc56f Mon Sep 17 00:00:00 2001
|
||||
From: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
Date: Thu, 28 Sep 2023 10:44:56 -0700
|
||||
Subject: [PATCH] linux: fix dscpremark extention doesn't set the type length
|
||||
|
||||
It needs to set up the type length for each extension.
|
||||
|
||||
Change-Id: Ia2087d7c4653045665c006ca9d637ff49d27fd92
|
||||
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
---
|
||||
net/netfilter/nf_conntrack_extend.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
--- a/net/netfilter/nf_conntrack_extend.c
|
||||
+++ b/net/netfilter/nf_conntrack_extend.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <net/netfilter/nf_conntrack_synproxy.h>
|
||||
#include <net/netfilter/nf_conntrack_act_ct.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
+#include <net/netfilter/nf_conntrack_dscpremark_ext.h>
|
||||
|
||||
#define NF_CT_EXT_PREALLOC 128u /* conntrack events are on by default */
|
||||
|
||||
@@ -54,6 +55,10 @@ static const u8 nf_ct_ext_type_len[NF_CT
|
||||
#if IS_ENABLED(CONFIG_NET_ACT_CT)
|
||||
[NF_CT_EXT_ACT_CT] = sizeof(struct nf_conn_act_ct_ext),
|
||||
#endif
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ [NF_CT_EXT_DSCPREMARK] = sizeof(struct nf_ct_dscpremark_ext),
|
||||
+#endif
|
||||
+
|
||||
};
|
||||
|
||||
static __always_inline unsigned int total_extension_size(void)
|
||||
@@ -86,6 +91,9 @@ static __always_inline unsigned int tota
|
||||
#if IS_ENABLED(CONFIG_NET_ACT_CT)
|
||||
+ sizeof(struct nf_conn_act_ct_ext)
|
||||
#endif
|
||||
+#ifdef CONFIG_NF_CONNTRACK_DSCPREMARK_EXT
|
||||
+ + sizeof(struct nf_ct_dscpremark_ext)
|
||||
+#endif
|
||||
;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
From 6f8beb8ec2047f645b488dd95be6f98ce0584165 Mon Sep 17 00:00:00 2001
|
||||
From: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
Date: Thu, 18 May 2023 08:47:34 -0700
|
||||
Subject: [PATCH 271/281] net: Add extra priv_flag support in netdevice
|
||||
|
||||
This patch adds a flag in struct net_device which
|
||||
is an extension to priv_flags and is used to
|
||||
check the type of device.
|
||||
|
||||
Change-Id: Ibb5a3f0c706e1b169b848aed7004aa4ea6d57069
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
Add GRE std support in device tree and priv_flags
|
||||
|
||||
Added dts support and priv flags support for GRE and
|
||||
to check the type of device
|
||||
|
||||
Change-Id: Ib05a32e9e5458c724c182187362116338d767169
|
||||
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
|
||||
Signed-off-by: Pavithra R <pavir@codeaurora.org>
|
||||
|
||||
drivers: ifb: Add flag to identify the IFB interface.
|
||||
|
||||
Add IFB flag in netdevice's ext priv flags and define an API
|
||||
to let other modules find out if the netdev is IFB or not.
|
||||
|
||||
Change-Id: I6dbdae521240b4a991069c2330d893ff38aec68d
|
||||
Signed-off-by: Manish Verma <maniverm@codeaurora.org>
|
||||
Signed-off-by: pavir <pavir@codeaurora.org>
|
||||
|
||||
net: add IFF_EXT_MAPT flag in net_device priv_flags_ext
|
||||
|
||||
Add IFF_EXT_MAPT flag in priv_flags_ext for MAP-T device.
|
||||
|
||||
Change-Id: I8aa1715c4b9c62b88eee1b40412cf4e734b2a337
|
||||
Signed-off-by: Suruchi Agarwal <quic_suruchia@quicinc.com>
|
||||
Signed-off-by: Murat Sezgin <quic_msezgin@quicinc.com>
|
||||
---
|
||||
drivers/net/ifb.c | 1 +
|
||||
include/linux/netdevice.h | 36 ++++++++++++++++++++++++++++++++++--
|
||||
net/ipv4/ip_gre.c | 2 +-
|
||||
net/ipv6/ip6_gre.c | 4 +---
|
||||
4 files changed, 37 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/ifb.c
|
||||
+++ b/drivers/net/ifb.c
|
||||
@@ -326,6 +326,7 @@ static void ifb_setup(struct net_device
|
||||
dev->flags |= IFF_NOARP;
|
||||
dev->flags &= ~IFF_MULTICAST;
|
||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||
+ dev->priv_flags_ext |= IFF_EXT_IFB; /* Mark the device as an IFB device. */
|
||||
netif_keep_dst(dev);
|
||||
eth_hw_addr_random(dev);
|
||||
dev->needs_free_netdev = true;
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -1781,6 +1781,32 @@ enum netdev_priv_flags {
|
||||
IFF_NO_IP_ALIGN = BIT_ULL(34),
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * enum netdev_priv_flags_ext - &struct net_device priv_flags_ext
|
||||
+ *
|
||||
+ * These flags are used to check for device type and can be
|
||||
+ * set and used by the drivers
|
||||
+ *
|
||||
+ * @IFF_EXT_TUN_TAP: device is a TUN/TAP device
|
||||
+ * @IFF_EXT_PPP_L2TPV2: device is a L2TPV2 device
|
||||
+ * @IFF_EXT_PPP_L2TPV3: device is a L2TPV3 device
|
||||
+ * @IFF_EXT_PPP_PPTP: device is a PPTP device
|
||||
+ * @IFF_EXT_GRE_V4_TAP: device is a GRE IPv4 TAP device
|
||||
+ * @IFF_EXT_GRE_V6_TAP: device is a GRE IPv6 TAP device
|
||||
+ * @IFF_EXT_IFB: device is an IFB device
|
||||
+ * @IFF_EXT_MAPT: device is an MAPT device
|
||||
+ */
|
||||
+enum netdev_priv_flags_ext {
|
||||
+ IFF_EXT_TUN_TAP = 1<<0,
|
||||
+ IFF_EXT_PPP_L2TPV2 = 1<<1,
|
||||
+ IFF_EXT_PPP_L2TPV3 = 1<<2,
|
||||
+ IFF_EXT_PPP_PPTP = 1<<3,
|
||||
+ IFF_EXT_GRE_V4_TAP = 1<<4,
|
||||
+ IFF_EXT_GRE_V6_TAP = 1<<5,
|
||||
+ IFF_EXT_IFB = 1<<6,
|
||||
+ IFF_EXT_MAPT = 1<<7,
|
||||
+};
|
||||
+
|
||||
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
|
||||
#define IFF_EBRIDGE IFF_EBRIDGE
|
||||
#define IFF_BONDING IFF_BONDING
|
||||
@@ -1901,6 +1927,8 @@ enum netdev_stat_type {
|
||||
* @xdp_features: XDP capability supported by the device
|
||||
* @priv_flags: Like 'flags' but invisible to userspace,
|
||||
* see if.h for the definitions
|
||||
+ * @priv_flags_ext: Extension for 'priv_flags'
|
||||
+ *
|
||||
* @gflags: Global flags ( kept as legacy )
|
||||
* @padded: How much padding added by alloc_netdev()
|
||||
* @operstate: RFC2863 operstate
|
||||
@@ -2146,6 +2174,7 @@ struct net_device {
|
||||
unsigned int flags;
|
||||
xdp_features_t xdp_features;
|
||||
unsigned long long priv_flags;
|
||||
+ unsigned int priv_flags_ext;
|
||||
const struct net_device_ops *netdev_ops;
|
||||
const struct xdp_metadata_ops *xdp_metadata_ops;
|
||||
int ifindex;
|
||||
@@ -5245,6 +5274,11 @@ static inline bool netif_is_failover_sla
|
||||
return dev->priv_flags & IFF_FAILOVER_SLAVE;
|
||||
}
|
||||
|
||||
+static inline bool netif_is_ifb_dev(const struct net_device *dev)
|
||||
+{
|
||||
+ return dev->priv_flags_ext & IFF_EXT_IFB;
|
||||
+}
|
||||
+
|
||||
/* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */
|
||||
static inline void netif_keep_dst(struct net_device *dev)
|
||||
{
|
||||
--- a/net/ipv4/ip_gre.c
|
||||
+++ b/net/ipv4/ip_gre.c
|
||||
@@ -828,7 +828,6 @@ static int ipgre_tunnel_ctl(struct net_d
|
||||
It allows to construct virtual multiprotocol broadcast "LAN"
|
||||
over the Internet, provided multicast routing is tuned.
|
||||
|
||||
-
|
||||
I have no idea was this bicycle invented before me,
|
||||
so that I had to set ARPHRD_IPGRE to a random value.
|
||||
I have an impression, that Cisco could make something similar,
|
||||
@@ -1337,6 +1336,7 @@ static void ipgre_tap_setup(struct net_d
|
||||
dev->netdev_ops = &gre_tap_netdev_ops;
|
||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
||||
+ dev->priv_flags_ext |= IFF_EXT_GRE_V4_TAP;
|
||||
ip_tunnel_setup(dev, gre_tap_net_id);
|
||||
}
|
||||
|
||||
--- a/net/ipv6/ip6_gre.c
|
||||
+++ b/net/ipv6/ip6_gre.c
|
||||
@@ -53,7 +53,6 @@
|
||||
#include <net/erspan.h>
|
||||
#include <net/dst_metadata.h>
|
||||
|
||||
-
|
||||
static bool log_ecn_error = true;
|
||||
module_param(log_ecn_error, bool, 0644);
|
||||
MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
|
||||
@@ -414,7 +413,6 @@ static void ip6gre_tunnel_uninit(struct
|
||||
netdev_put(dev, &t->dev_tracker);
|
||||
}
|
||||
|
||||
-
|
||||
static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
||||
u8 type, u8 code, int offset, __be32 info)
|
||||
{
|
||||
@@ -1618,7 +1616,6 @@ static int __net_init ip6gre_init_net(st
|
||||
*/
|
||||
ign->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL;
|
||||
|
||||
-
|
||||
ip6gre_fb_tunnel_init(ign->fb_tunnel_dev);
|
||||
ign->fb_tunnel_dev->rtnl_link_ops = &ip6gre_link_ops;
|
||||
|
||||
@@ -1941,6 +1938,7 @@ static void ip6gre_tap_setup(struct net_
|
||||
|
||||
dev->priv_flags &= ~IFF_TX_SKB_SHARING;
|
||||
dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
||||
+ dev->priv_flags_ext |= IFF_EXT_GRE_V6_TAP;
|
||||
netif_keep_dst(dev);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
--- a/include/linux/skbuff.h
|
||||
+++ b/include/linux/skbuff.h
|
||||
@@ -762,6 +762,7 @@ typedef unsigned char *sk_buff_data_t;
|
||||
* @offload_fwd_mark: Packet was L2-forwarded in hardware
|
||||
* @offload_l3_fwd_mark: Packet was L3-forwarded in hardware
|
||||
* @tc_skip_classify: do not classify packet. set by IFB device
|
||||
+ * @tc_skip_classify_offload: do not classify packet set by offload IFB device
|
||||
* @tc_at_ingress: used within tc_classify to distinguish in/egress
|
||||
* @redirected: packet was redirected by packet classifier
|
||||
* @from_ingress: packet was redirected from the ingress path
|
||||
@@ -970,6 +971,12 @@ struct sk_buff {
|
||||
__u8 offload_fwd_mark:1;
|
||||
__u8 offload_l3_fwd_mark:1;
|
||||
#endif
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ __u8 tc_skip_classify:1;
|
||||
+ __u8 tc_at_ingress:1;
|
||||
+ __u8 tc_skip_classify_offload:1;
|
||||
+ __u16 tc_verd_qca_nss;
|
||||
+#endif
|
||||
__u8 redirected:1;
|
||||
#ifdef CONFIG_NET_REDIRECT
|
||||
__u8 from_ingress:1;
|
||||
--- a/include/uapi/linux/pkt_cls.h
|
||||
+++ b/include/uapi/linux/pkt_cls.h
|
||||
@@ -139,6 +139,7 @@ enum tca_id {
|
||||
TCA_ID_MPLS,
|
||||
TCA_ID_CT,
|
||||
TCA_ID_GATE,
|
||||
+ TCA_ID_MIRRED_NSS,
|
||||
/* other actions go here */
|
||||
__TCA_ID_MAX = 255
|
||||
};
|
||||
@@ -817,4 +818,14 @@ enum {
|
||||
TCF_EM_OPND_LT
|
||||
};
|
||||
|
||||
+
|
||||
+#define _TC_MAKE32(x) ((x))
|
||||
+#define _TC_MAKEMASK1(n) (_TC_MAKE32(1) << _TC_MAKE32(n))
|
||||
+
|
||||
+#define TC_NCLS _TC_MAKEMASK1(8)
|
||||
+#define TC_NCLS_NSS _TC_MAKEMASK1(12)
|
||||
+#define SET_TC_NCLS_NSS(v) ( TC_NCLS_NSS | ((v) & ~TC_NCLS_NSS))
|
||||
+#define CLR_TC_NCLS_NSS(v) ( (v) & ~TC_NCLS_NSS)
|
||||
+
|
||||
+
|
||||
#endif
|
||||
--- a/include/linux/timer.h
|
||||
+++ b/include/linux/timer.h
|
||||
@@ -17,6 +17,7 @@ struct timer_list {
|
||||
unsigned long expires;
|
||||
void (*function)(struct timer_list *);
|
||||
u32 flags;
|
||||
+ unsigned long cust_data;
|
||||
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
struct lockdep_map lockdep_map;
|
||||
--- a/drivers/net/ifb.c
|
||||
+++ b/drivers/net/ifb.c
|
||||
@@ -151,6 +151,31 @@ resched:
|
||||
|
||||
}
|
||||
|
||||
+void ifb_update_offload_stats(struct net_device *dev, struct pcpu_sw_netstats *offload_stats)
|
||||
+{
|
||||
+ struct ifb_dev_private *dp;
|
||||
+ struct ifb_q_private *txp;
|
||||
+
|
||||
+ if (!dev || !offload_stats) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!(dev->priv_flags_ext & IFF_EXT_IFB)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dp = netdev_priv(dev);
|
||||
+ txp = dp->tx_private;
|
||||
+
|
||||
+ u64_stats_update_begin(&txp->rsync);
|
||||
+ txp->rx_packets += offload_stats->rx_packets;
|
||||
+ txp->rx_bytes += offload_stats->rx_bytes;
|
||||
+ txp->tx_packets += offload_stats->tx_packets;
|
||||
+ txp->tx_bytes += offload_stats->tx_bytes;
|
||||
+ u64_stats_update_end(&txp->rsync);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ifb_update_offload_stats);
|
||||
+
|
||||
static void ifb_stats64(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -4730,6 +4730,15 @@ void dev_uc_flush(struct net_device *dev
|
||||
void dev_uc_init(struct net_device *dev);
|
||||
|
||||
/**
|
||||
+ * ifb_update_offload_stats - Update the IFB interface stats
|
||||
+ * @dev: IFB device to update the stats
|
||||
+ * @offload_stats: per CPU stats structure
|
||||
+ *
|
||||
+ * Allows update of IFB stats when flows are offloaded to an accelerator.
|
||||
+ **/
|
||||
+void ifb_update_offload_stats(struct net_device *dev, struct pcpu_sw_netstats *offload_stats);
|
||||
+
|
||||
+/**
|
||||
* __dev_uc_sync - Synchonize device's unicast list
|
||||
* @dev: device to sync
|
||||
* @sync: function to call if address should be added
|
||||
--- a/include/uapi/linux/pkt_sched.h
|
||||
+++ b/include/uapi/linux/pkt_sched.h
|
||||
@@ -1306,4 +1306,248 @@ enum {
|
||||
|
||||
#define TCA_ETS_MAX (__TCA_ETS_MAX - 1)
|
||||
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSS_ACCEL_MODE_NSS_FW,
|
||||
+ TCA_NSS_ACCEL_MODE_PPE,
|
||||
+ TCA_NSS_ACCEL_MODE_MAX
|
||||
+};
|
||||
+
|
||||
+/* NSSFIFO section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSFIFO_UNSPEC,
|
||||
+ TCA_NSSFIFO_PARMS,
|
||||
+ __TCA_NSSFIFO_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSFIFO_MAX (__TCA_NSSFIFO_MAX - 1)
|
||||
+
|
||||
+struct tc_nssfifo_qopt {
|
||||
+ __u32 limit; /* Queue length: bytes for bfifo, packets for pfifo */
|
||||
+ __u8 set_default; /* Sets qdisc to be the default qdisc for enqueue */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSWRED section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSWRED_UNSPEC,
|
||||
+ TCA_NSSWRED_PARMS,
|
||||
+ __TCA_NSSWRED_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSWRED_MAX (__TCA_NSSWRED_MAX - 1)
|
||||
+#define NSSWRED_CLASS_MAX 6
|
||||
+struct tc_red_alg_parameter {
|
||||
+ __u32 min; /* qlen_avg < min: pkts are all enqueued */
|
||||
+ __u32 max; /* qlen_avg > max: pkts are all dropped */
|
||||
+ __u32 probability;/* Drop probability at qlen_avg = max */
|
||||
+ __u32 exp_weight_factor;/* exp_weight_factor for calculate qlen_avg */
|
||||
+};
|
||||
+
|
||||
+struct tc_nsswred_traffic_class {
|
||||
+ __u32 limit; /* Queue length */
|
||||
+ __u32 weight_mode_value; /* Weight mode value */
|
||||
+ struct tc_red_alg_parameter rap;/* Parameters for RED alg */
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * Weight modes for WRED
|
||||
+ */
|
||||
+enum tc_nsswred_weight_modes {
|
||||
+ TC_NSSWRED_WEIGHT_MODE_DSCP = 0,/* Weight mode is DSCP */
|
||||
+ TC_NSSWRED_WEIGHT_MODES, /* Must be last */
|
||||
+};
|
||||
+
|
||||
+struct tc_nsswred_qopt {
|
||||
+ __u32 limit; /* Queue length */
|
||||
+ enum tc_nsswred_weight_modes weight_mode;
|
||||
+ /* Weight mode */
|
||||
+ __u32 traffic_classes; /* How many traffic classes: DPs */
|
||||
+ __u32 def_traffic_class; /* Default traffic if no match: def_DP */
|
||||
+ __u32 traffic_id; /* The traffic id to be configured: DP */
|
||||
+ __u32 weight_mode_value; /* Weight mode value */
|
||||
+ struct tc_red_alg_parameter rap;/* RED algorithm parameters */
|
||||
+ struct tc_nsswred_traffic_class tntc[NSSWRED_CLASS_MAX];
|
||||
+ /* Traffic settings for dumpping */
|
||||
+ __u8 ecn; /* Setting ECN bit or dropping */
|
||||
+ __u8 set_default; /* Sets qdisc to be the default for enqueue */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSCODEL section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSCODEL_UNSPEC,
|
||||
+ TCA_NSSCODEL_PARMS,
|
||||
+ __TCA_NSSCODEL_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSCODEL_MAX (__TCA_NSSCODEL_MAX - 1)
|
||||
+
|
||||
+struct tc_nsscodel_qopt {
|
||||
+ __u32 target; /* Acceptable queueing delay */
|
||||
+ __u32 limit; /* Max number of packets that can be held in the queue */
|
||||
+ __u32 interval; /* Monitoring interval */
|
||||
+ __u32 flows; /* Number of flow buckets */
|
||||
+ __u32 quantum; /* Weight (in bytes) used for DRR of flow buckets */
|
||||
+ __u8 ecn; /* 0 - disable ECN, 1 - enable ECN */
|
||||
+ __u8 set_default; /* Sets qdisc to be the default qdisc for enqueue */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+struct tc_nsscodel_xstats {
|
||||
+ __u32 peak_queue_delay; /* Peak delay experienced by a dequeued packet */
|
||||
+ __u32 peak_drop_delay; /* Peak delay experienced by a dropped packet */
|
||||
+};
|
||||
+
|
||||
+/* NSSFQ_CODEL section */
|
||||
+
|
||||
+struct tc_nssfq_codel_xstats {
|
||||
+ __u32 new_flow_count; /* Total number of new flows seen */
|
||||
+ __u32 new_flows_len; /* Current number of new flows */
|
||||
+ __u32 old_flows_len; /* Current number of old flows */
|
||||
+ __u32 ecn_mark; /* Number of packets marked with ECN */
|
||||
+ __u32 drop_overlimit; /* Number of packets dropped due to overlimit */
|
||||
+ __u32 maxpacket; /* The largest packet seen so far in the queue */
|
||||
+};
|
||||
+
|
||||
+/* NSSTBL section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSTBL_UNSPEC,
|
||||
+ TCA_NSSTBL_PARMS,
|
||||
+ __TCA_NSSTBL_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSTBL_MAX (__TCA_NSSTBL_MAX - 1)
|
||||
+
|
||||
+struct tc_nsstbl_qopt {
|
||||
+ __u32 burst; /* Maximum burst size */
|
||||
+ __u32 rate; /* Limiting rate of TBF */
|
||||
+ __u32 peakrate; /* Maximum rate at which TBF is allowed to send */
|
||||
+ __u32 mtu; /* Max size of packet, or minumim burst size */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSPRIO section */
|
||||
+
|
||||
+#define TCA_NSSPRIO_MAX_BANDS 256
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSPRIO_UNSPEC,
|
||||
+ TCA_NSSPRIO_PARMS,
|
||||
+ __TCA_NSSPRIO_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSPRIO_MAX (__TCA_NSSPRIO_MAX - 1)
|
||||
+
|
||||
+struct tc_nssprio_qopt {
|
||||
+ __u32 bands; /* Number of bands */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSBF section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSBF_UNSPEC,
|
||||
+ TCA_NSSBF_CLASS_PARMS,
|
||||
+ TCA_NSSBF_QDISC_PARMS,
|
||||
+ __TCA_NSSBF_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSBF_MAX (__TCA_NSSBF_MAX - 1)
|
||||
+
|
||||
+struct tc_nssbf_class_qopt {
|
||||
+ __u32 burst; /* Maximum burst size */
|
||||
+ __u32 rate; /* Allowed bandwidth for this class */
|
||||
+ __u32 mtu; /* MTU of the associated interface */
|
||||
+ __u32 quantum; /* Quantum allocation for DRR */
|
||||
+};
|
||||
+
|
||||
+struct tc_nssbf_qopt {
|
||||
+ __u16 defcls; /* Default class value */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSWRR section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSWRR_UNSPEC,
|
||||
+ TCA_NSSWRR_CLASS_PARMS,
|
||||
+ TCA_NSSWRR_QDISC_PARMS,
|
||||
+ __TCA_NSSWRR_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSWRR_MAX (__TCA_NSSWRR_MAX - 1)
|
||||
+
|
||||
+struct tc_nsswrr_class_qopt {
|
||||
+ __u32 quantum; /* Weight associated to this class */
|
||||
+};
|
||||
+
|
||||
+struct tc_nsswrr_qopt {
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSWFQ section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSWFQ_UNSPEC,
|
||||
+ TCA_NSSWFQ_CLASS_PARMS,
|
||||
+ TCA_NSSWFQ_QDISC_PARMS,
|
||||
+ __TCA_NSSWFQ_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSWFQ_MAX (__TCA_NSSWFQ_MAX - 1)
|
||||
+
|
||||
+struct tc_nsswfq_class_qopt {
|
||||
+ __u32 quantum; /* Weight associated to this class */
|
||||
+};
|
||||
+
|
||||
+struct tc_nsswfq_qopt {
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSHTB section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSHTB_UNSPEC,
|
||||
+ TCA_NSSHTB_CLASS_PARMS,
|
||||
+ TCA_NSSHTB_QDISC_PARMS,
|
||||
+ __TCA_NSSHTB_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSHTB_MAX (__TCA_NSSHTB_MAX - 1)
|
||||
+
|
||||
+struct tc_nsshtb_class_qopt {
|
||||
+ __u32 burst; /* Allowed burst size */
|
||||
+ __u32 rate; /* Allowed bandwidth for this class */
|
||||
+ __u32 cburst; /* Maximum burst size */
|
||||
+ __u32 crate; /* Maximum bandwidth for this class */
|
||||
+ __u32 quantum; /* Quantum allocation for DRR */
|
||||
+ __u32 priority; /* Priority value associated with this class */
|
||||
+ __u32 overhead; /* Overhead in bytes per packet */
|
||||
+};
|
||||
+
|
||||
+struct tc_nsshtb_qopt {
|
||||
+ __u32 r2q; /* Rate to quantum ratio */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
+/* NSSBLACKHOLE section */
|
||||
+
|
||||
+enum {
|
||||
+ TCA_NSSBLACKHOLE_UNSPEC,
|
||||
+ TCA_NSSBLACKHOLE_PARMS,
|
||||
+ __TCA_NSSBLACKHOLE_MAX
|
||||
+};
|
||||
+
|
||||
+#define TCA_NSSBLACKHOLE_MAX (__TCA_NSSBLACKHOLE_MAX - 1)
|
||||
+
|
||||
+struct tc_nssblackhole_qopt {
|
||||
+ __u8 set_default; /* Sets qdisc to be the default qdisc for enqueue */
|
||||
+ __u8 accel_mode; /* Dictates which data plane offloads the qdisc */
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
--- a/net/sched/sch_api.c
|
||||
+++ b/net/sched/sch_api.c
|
||||
@@ -2399,4 +2399,26 @@ static int __init pktsched_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
+bool tcf_destroy(struct tcf_proto *tp, bool force)
|
||||
+{
|
||||
+ tp->ops->destroy(tp, force, NULL);
|
||||
+ module_put(tp->ops->owner);
|
||||
+ kfree_rcu(tp, rcu);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+void tcf_destroy_chain(struct tcf_proto __rcu **fl)
|
||||
+{
|
||||
+ struct tcf_proto *tp;
|
||||
+
|
||||
+ while ((tp = rtnl_dereference(*fl)) != NULL) {
|
||||
+ RCU_INIT_POINTER(*fl, tp->next);
|
||||
+ tcf_destroy(tp, true);
|
||||
+ }
|
||||
+}
|
||||
+EXPORT_SYMBOL(tcf_destroy_chain);
|
||||
+
|
||||
+
|
||||
subsys_initcall(pktsched_init);
|
||||
--- a/net/sched/sch_generic.c
|
||||
+++ b/net/sched/sch_generic.c
|
||||
@@ -1059,7 +1059,7 @@ static void qdisc_free_cb(struct rcu_hea
|
||||
qdisc_free(q);
|
||||
}
|
||||
|
||||
-static void __qdisc_destroy(struct Qdisc *qdisc)
|
||||
+void __qdisc_destroy(struct Qdisc *qdisc)
|
||||
{
|
||||
const struct Qdisc_ops *ops = qdisc->ops;
|
||||
|
||||
@@ -1091,6 +1091,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
|
||||
|
||||
__qdisc_destroy(qdisc);
|
||||
}
|
||||
+EXPORT_SYMBOL(__qdisc_destroy);
|
||||
|
||||
void qdisc_put(struct Qdisc *qdisc)
|
||||
{
|
||||
--- a/include/net/sch_generic.h
|
||||
+++ b/include/net/sch_generic.h
|
||||
@@ -94,6 +94,7 @@ struct Qdisc {
|
||||
#define TCQ_F_INVISIBLE 0x80 /* invisible by default in dump */
|
||||
#define TCQ_F_NOLOCK 0x100 /* qdisc does not require locking */
|
||||
#define TCQ_F_OFFLOADED 0x200 /* qdisc is offloaded to HW */
|
||||
+#define TCQ_F_NSS 0x1000 /* NSS qdisc flag. */
|
||||
u32 limit;
|
||||
const struct Qdisc_ops *ops;
|
||||
struct qdisc_size_table __rcu *stab;
|
||||
@@ -752,6 +753,40 @@ static inline bool skb_skip_tc_classify(
|
||||
return false;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Set skb classify bit field.
|
||||
+ */
|
||||
+static inline void skb_set_tc_classify_offload(struct sk_buff *skb)
|
||||
+{
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ skb->tc_skip_classify_offload = 1;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Clear skb classify bit field.
|
||||
+ */
|
||||
+static inline void skb_clear_tc_classify_offload(struct sk_buff *skb)
|
||||
+{
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ skb->tc_skip_classify_offload = 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Skip skb processing if sent from ifb dev.
|
||||
+ */
|
||||
+static inline bool skb_skip_tc_classify_offload(struct sk_buff *skb)
|
||||
+{
|
||||
+#ifdef CONFIG_NET_CLS_ACT
|
||||
+ if (skb->tc_skip_classify_offload) {
|
||||
+ skb_clear_tc_classify_offload(skb);
|
||||
+ return true;
|
||||
+ }
|
||||
+#endif
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
/* Reset all TX qdiscs greater than index of a device. */
|
||||
static inline void qdisc_reset_all_tx_gt(struct net_device *dev, unsigned int i)
|
||||
{
|
||||
@@ -1323,4 +1358,9 @@ static inline void qdisc_synchronize(con
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
+
|
||||
+void qdisc_destroy(struct Qdisc *qdisc);
|
||||
+void tcf_destroy_chain(struct tcf_proto __rcu **fl);
|
||||
+
|
||||
+
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
From 507188b4c93e2641fd271bd08d881136a1de2068 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
Date: Thu, 14 Oct 2021 08:50:03 -0700
|
||||
Subject: [PATCH 260/281] net: fix potential memory leak
|
||||
|
||||
When A packets come from a disabled port, if it is not a accepted
|
||||
EAPOL, it has no chance to get freed.
|
||||
|
||||
Change-Id: Ib2bddeb53f2117bcc803d11912471a8456a3148a
|
||||
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
---
|
||||
net/bridge/br_input.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/net/bridge/br_input.c
|
||||
+++ b/net/bridge/br_input.c
|
||||
@@ -461,7 +461,7 @@ forward:
|
||||
return RX_HANDLER_PASS;
|
||||
}
|
||||
}
|
||||
- break;
|
||||
+ goto drop;
|
||||
|
||||
case BR_STATE_FORWARDING:
|
||||
case BR_STATE_LEARNING:
|
||||
@@ -0,0 +1,39 @@
|
||||
From af7d2a61b63bdb996746d38288842624e662a447 Mon Sep 17 00:00:00 2001
|
||||
From: Ratheesh Kannoth <quic_rkannoth@quicinc.com>
|
||||
Date: Fri, 17 Dec 2021 19:17:58 +0530
|
||||
Subject: [PATCH 261/281] net: Move skb_vlan_untag(skb) after sfe hook
|
||||
|
||||
Change-Id: I5a019761f363dd81bf5e52eea606b9076f22e6af
|
||||
Signed-off-by: Ratheesh Kannoth <quic_rkannoth@quicinc.com>
|
||||
---
|
||||
net/core/dev.c | 19 ++++++-------------
|
||||
1 file changed, 6 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -5455,12 +5455,6 @@ another_round:
|
||||
}
|
||||
}
|
||||
|
||||
- if (eth_type_vlan(skb->protocol)) {
|
||||
- skb = skb_vlan_untag(skb);
|
||||
- if (unlikely(!skb))
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
fast_recv = rcu_dereference(athrs_fast_nat_recv);
|
||||
if (fast_recv) {
|
||||
if (fast_recv(skb)) {
|
||||
@@ -5469,6 +5463,12 @@ another_round:
|
||||
}
|
||||
}
|
||||
|
||||
+ if (eth_type_vlan(skb->protocol)) {
|
||||
+ skb = skb_vlan_untag(skb);
|
||||
+ if (unlikely(!skb))
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
if (skb_skip_tc_classify(skb))
|
||||
goto skip_classify;
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
From 120ae502af169310aa53359d4faf2494dcee6927 Mon Sep 17 00:00:00 2001
|
||||
From: Tallapragada Kalyan <quic_ktallapr@quicinc.com>
|
||||
Date: Thu, 9 Jun 2022 09:32:38 +0530
|
||||
Subject: [PATCH 267/281] net: set skb's fast_xmit flag in dev_fast_xmit API
|
||||
|
||||
set skb's fast_xmit flag in dev_fast_xmit API for linear packets
|
||||
WiFi tx path can avoid some overhead due to checks based on this flag
|
||||
|
||||
Change-Id: Ied29f9d615d0cf48dd9dcd7fcf0fb210eb259a8f
|
||||
Signed-off-by: Tallapragada Kalyan <quic_ktallapr@quicinc.com>
|
||||
---
|
||||
include/linux/skbuff.h | 2 ++
|
||||
net/core/dev.c | 4 ++++
|
||||
2 files changed, 6 insertions(+)
|
||||
|
||||
--- a/include/linux/skbuff.h
|
||||
+++ b/include/linux/skbuff.h
|
||||
@@ -992,6 +992,8 @@ struct sk_buff {
|
||||
__u8 csum_not_inet:1;
|
||||
#endif
|
||||
__u8 fast_forwarded:1;
|
||||
+ /* Linear packets processed by dev_fast_xmit() */
|
||||
+ __u8 fast_xmit:1;
|
||||
/* 1 or 3 bit hole */
|
||||
|
||||
#if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS)
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -4305,6 +4305,144 @@ struct netdev_queue *netdev_core_pick_tx
|
||||
}
|
||||
|
||||
/**
|
||||
+ * dev_fast_xmit_vp - fast xmit the skb to a PPE virtual port
|
||||
+ * @skb:buffer to transmit
|
||||
+ * @dev: the device to be transmited to
|
||||
+ * sucessful return true
|
||||
+ * failed return false
|
||||
+ */
|
||||
+bool dev_fast_xmit_vp(struct sk_buff *skb,
|
||||
+ struct net_device *dev)
|
||||
+{
|
||||
+ struct netdev_queue *txq;
|
||||
+ int cpu;
|
||||
+ netdev_tx_t rc;
|
||||
+
|
||||
+ if (unlikely(!(dev->flags & IFF_UP))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (unlikely(skb_is_nonlinear(skb))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ rcu_read_lock_bh();
|
||||
+ cpu = smp_processor_id();
|
||||
+
|
||||
+ /*
|
||||
+ * TODO: Skip this altogether and eventually move this call to ppe_vp
|
||||
+ * this would avoid multiple function calls when giving packet to wifi VAP.
|
||||
+ */
|
||||
+ txq = netdev_core_pick_tx(dev, skb, NULL);
|
||||
+
|
||||
+ if (likely(txq->xmit_lock_owner != cpu)) {
|
||||
+#define FAST_VP_HARD_TX_LOCK(txq, cpu) { \
|
||||
+ __netif_tx_lock(txq, cpu); \
|
||||
+}
|
||||
+
|
||||
+#define FAST_VP_HARD_TX_UNLOCK(txq) { \
|
||||
+ __netif_tx_unlock(txq); \
|
||||
+}
|
||||
+ skb->fast_xmit = 1;
|
||||
+ FAST_VP_HARD_TX_LOCK(txq, cpu);
|
||||
+ if (likely(!netif_xmit_stopped(txq))) {
|
||||
+ rc = netdev_start_xmit(skb, dev, txq, 0);
|
||||
+ if (unlikely(!dev_xmit_complete(rc))) {
|
||||
+ FAST_VP_HARD_TX_UNLOCK(txq);
|
||||
+ goto q_xmit;
|
||||
+ }
|
||||
+ FAST_VP_HARD_TX_UNLOCK(txq);
|
||||
+ rcu_read_unlock_bh();
|
||||
+ return true;
|
||||
+ }
|
||||
+ FAST_VP_HARD_TX_UNLOCK(txq);
|
||||
+ }
|
||||
+q_xmit:
|
||||
+ skb->fast_xmit = 0;
|
||||
+ rcu_read_unlock_bh();
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL(dev_fast_xmit_vp);
|
||||
+
|
||||
+/**
|
||||
+ * dev_fast_xmit - fast xmit the skb
|
||||
+ * @skb:buffer to transmit
|
||||
+ * @dev: the device to be transmited to
|
||||
+ * @features: the skb features could bed used
|
||||
+ * sucessful return true
|
||||
+ * failed return false
|
||||
+ */
|
||||
+bool dev_fast_xmit(struct sk_buff *skb,
|
||||
+ struct net_device *dev,
|
||||
+ netdev_features_t features)
|
||||
+{
|
||||
+ struct netdev_queue *txq;
|
||||
+ int cpu;
|
||||
+ netdev_tx_t rc;
|
||||
+
|
||||
+ /* the fast_xmit flag will avoid multiple checks in wifi xmit path */
|
||||
+ if (likely(!skb_is_nonlinear(skb)))
|
||||
+ skb->fast_xmit = 1;
|
||||
+
|
||||
+ if (unlikely(!(dev->flags & IFF_UP))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (unlikely(skb_needs_linearize(skb, features))) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ rcu_read_lock_bh();
|
||||
+ cpu = smp_processor_id();
|
||||
+
|
||||
+ /* If device don't need the dst, release it now, otherwise make sure
|
||||
+ * the refcount increased.
|
||||
+ */
|
||||
+ if (likely(dev->priv_flags & IFF_XMIT_DST_RELEASE)) {
|
||||
+ skb_dst_drop(skb);
|
||||
+ } else {
|
||||
+ skb_dst_force(skb);
|
||||
+ }
|
||||
+
|
||||
+ txq = netdev_core_pick_tx(dev, skb, NULL);
|
||||
+
|
||||
+ if (likely(txq->xmit_lock_owner != cpu)) {
|
||||
+#define FAST_HARD_TX_LOCK(features, txq, cpu) { \
|
||||
+ if ((features & NETIF_F_LLTX) == 0) { \
|
||||
+ __netif_tx_lock(txq, cpu); \
|
||||
+ } else { \
|
||||
+ __netif_tx_acquire(txq); \
|
||||
+ } \
|
||||
+}
|
||||
+
|
||||
+#define FAST_HARD_TX_UNLOCK(features, txq) { \
|
||||
+ if ((features & NETIF_F_LLTX) == 0) { \
|
||||
+ __netif_tx_unlock(txq); \
|
||||
+ } else { \
|
||||
+ __netif_tx_release(txq); \
|
||||
+ } \
|
||||
+}
|
||||
+ netdev_features_t dev_features = dev->features;
|
||||
+ FAST_HARD_TX_LOCK(dev_features, txq, cpu);
|
||||
+ if (likely(!netif_xmit_stopped(txq))) {
|
||||
+ rc = netdev_start_xmit(skb, dev, txq, 0);
|
||||
+ if (unlikely(!dev_xmit_complete(rc))) {
|
||||
+ FAST_HARD_TX_UNLOCK(dev_features, txq);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ FAST_HARD_TX_UNLOCK(dev_features, txq);
|
||||
+ rcu_read_unlock_bh();
|
||||
+ return true;
|
||||
+ }
|
||||
+ FAST_HARD_TX_UNLOCK(dev_features, txq);
|
||||
+ }
|
||||
+fail:
|
||||
+ rcu_read_unlock_bh();
|
||||
+ return false;
|
||||
+}
|
||||
+EXPORT_SYMBOL(dev_fast_xmit);
|
||||
+
|
||||
+/**
|
||||
* __dev_queue_xmit() - transmit a buffer
|
||||
* @skb: buffer to transmit
|
||||
* @sb_dev: suboordinate device used for L2 forwarding offload
|
||||
@@ -0,0 +1,52 @@
|
||||
From 246b87f0daff042ad215c9c55b411e70ae5406e2 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
Date: Mon, 25 Apr 2022 13:54:20 -0700
|
||||
Subject: [PATCH 263/281] net: do time update rather than fully update in the
|
||||
fdb
|
||||
|
||||
keep the fdb up to date when do refresh.
|
||||
|
||||
Change-Id: Ib0297f11920b66bb573ef41f8a09da9ac0d774af
|
||||
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
---
|
||||
include/linux/if_bridge.h | 1 +
|
||||
net/bridge/br_fdb.c | 18 ++++++++++++++++++
|
||||
2 files changed, 19 insertions(+)
|
||||
|
||||
--- a/include/linux/if_bridge.h
|
||||
+++ b/include/linux/if_bridge.h
|
||||
@@ -78,6 +78,7 @@ extern struct net_device *br_port_dev_ge
|
||||
struct sk_buff *skb,
|
||||
unsigned int cookie);
|
||||
extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr);
|
||||
+extern void br_fdb_entry_refresh(struct net_device *dev, const char *addr, __u16 vid);
|
||||
extern void br_dev_update_stats(struct net_device *dev,
|
||||
struct rtnl_link_stats64 *nlstats);
|
||||
extern struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||
--- a/net/bridge/br_fdb.c
|
||||
+++ b/net/bridge/br_fdb.c
|
||||
@@ -1006,6 +1006,24 @@ void br_refresh_fdb_entry(struct net_dev
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(br_refresh_fdb_entry);
|
||||
|
||||
+/* Update timestamp of FDB entries for bridge packets being forwarded by offload engines */
|
||||
+void br_fdb_entry_refresh(struct net_device *dev, const char *addr, __u16 vid)
|
||||
+{
|
||||
+ struct net_bridge_fdb_entry *fdb;
|
||||
+ struct net_bridge_port *p = br_port_get_rcu(dev);
|
||||
+
|
||||
+ if (!p || p->state == BR_STATE_DISABLED)
|
||||
+ return;
|
||||
+
|
||||
+ rcu_read_lock();
|
||||
+ fdb = fdb_find_rcu(&p->br->fdb_hash_tbl, addr, vid);
|
||||
+ if (likely(fdb)) {
|
||||
+ fdb->updated = jiffies;
|
||||
+ }
|
||||
+ rcu_read_unlock();
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(br_fdb_entry_refresh);
|
||||
+
|
||||
/* Look up the MAC address in the device's bridge fdb table */
|
||||
struct net_bridge_fdb_entry *br_fdb_has_entry(struct net_device *dev,
|
||||
const char *addr, __u16 vid)
|
||||
@@ -0,0 +1,31 @@
|
||||
From 782c8dfcfeff6115a857ca9299df35cffaf8d476 Mon Sep 17 00:00:00 2001
|
||||
From: Tushar Ganatra <quic_tganatra@quicinc.com>
|
||||
Date: Wed, 6 Dec 2023 12:45:26 +0530
|
||||
Subject: [PATCH] dev_queue_xmit: Reset skb->fast_xmit flag in slow path
|
||||
transmit
|
||||
|
||||
Reset skb->fast_xmit flag in "dev_queue_xmit". This avoids a combination
|
||||
scenarios like PPPoE with DS-Lite or other tunnels where one rule is matched
|
||||
with sfe and was transmitted in fast path and the inner is transmitted through
|
||||
slow path.
|
||||
|
||||
Change-Id: Ia12907f459c15747daf00a216672e903c924332a
|
||||
Signed-off-by: Tushar Ganatra <quic_tganatra@quicinc.com>
|
||||
---
|
||||
net/core/dev.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -4474,6 +4474,11 @@ int __dev_queue_xmit(struct sk_buff *skb
|
||||
skb_reset_mac_header(skb);
|
||||
skb_assert_len(skb);
|
||||
|
||||
+ /*
|
||||
+ * if the skb landed in dev_queue_xmit then its not fast transmitted
|
||||
+ * reset this flag for further processing.
|
||||
+ */
|
||||
+ skb->fast_xmit = 0;
|
||||
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_SCHED_TSTAMP))
|
||||
__skb_tstamp_tx(skb, NULL, NULL, skb->sk, SCM_TSTAMP_SCHED);
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
--- a/net/bridge/br_forward.c
|
||||
+++ b/net/bridge/br_forward.c
|
||||
@@ -24,11 +24,29 @@ static inline int should_deliver(const s
|
||||
struct net_bridge_vlan_group *vg;
|
||||
|
||||
vg = nbp_vlan_group_rcu(p);
|
||||
- return (((p->flags & BR_HAIRPIN_MODE) && !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
|
||||
- || skb->dev != p->dev) &&
|
||||
- (br_mst_is_enabled(p->br) || p->state == BR_STATE_FORWARDING) &&
|
||||
- br_allowed_egress(vg, skb) && nbp_switchdev_allowed_egress(p, skb) &&
|
||||
- !br_skb_isolated(p, skb);
|
||||
+
|
||||
+ if ((skb->dev != p->dev) &&
|
||||
+ br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING &&
|
||||
+ nbp_switchdev_allowed_egress(p, skb) &&
|
||||
+ !br_skb_isolated(p, skb)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if ((skb->dev == p->dev) &&
|
||||
+ (p->flags & BR_HAIRPIN_MODE) &&
|
||||
+ br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING) {
|
||||
+
|
||||
+ /* Allow hairpin only on WLAN netdevices.
|
||||
+ * For ethernet interfaces, hairpin not allowed
|
||||
+ * due to issue with switchdevs. */
|
||||
+ if ( skb->dev->ieee80211_ptr == NULL) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
}
|
||||
|
||||
int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
@@ -0,0 +1,56 @@
|
||||
From d34da78089af855bf1406cea24342b0cc4c8225d Mon Sep 17 00:00:00 2001
|
||||
From: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
Date: Thu, 4 Apr 2024 16:01:38 -0700
|
||||
Subject: [PATCH] [net] [bridge] Allow unicast loop back when hairpin enabled
|
||||
|
||||
disable multicast go back to the original device for non wireless
|
||||
device.
|
||||
|
||||
Change-Id: Ia5124d2c3d602f71d444f4ac800ddae4b608e4c2
|
||||
Signed-off-by: Ken Zhu <quic_guigenz@quicinc.com>
|
||||
---
|
||||
net/bridge/br_forward.c | 33 +++++++++++----------------------
|
||||
1 file changed, 11 insertions(+), 22 deletions(-)
|
||||
|
||||
--- a/net/bridge/br_forward.c
|
||||
+++ b/net/bridge/br_forward.c
|
||||
@@ -25,28 +25,17 @@ static inline int should_deliver(const s
|
||||
|
||||
vg = nbp_vlan_group_rcu(p);
|
||||
|
||||
- if ((skb->dev != p->dev) &&
|
||||
- br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING &&
|
||||
- nbp_switchdev_allowed_egress(p, skb) &&
|
||||
- !br_skb_isolated(p, skb)) {
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- if ((skb->dev == p->dev) &&
|
||||
- (p->flags & BR_HAIRPIN_MODE) &&
|
||||
- br_allowed_egress(vg, skb) && p->state == BR_STATE_FORWARDING) {
|
||||
-
|
||||
- /* Allow hairpin only on WLAN netdevices.
|
||||
- * For ethernet interfaces, hairpin not allowed
|
||||
- * due to issue with switchdevs. */
|
||||
- if ( skb->dev->ieee80211_ptr == NULL) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ /*
|
||||
+ * When hairpin enabled, don't allow multicast go back
|
||||
+ * to the original non-wireless device.
|
||||
+ * it could cause fdb learning issue to connected switch.
|
||||
+ */
|
||||
+ return (((p->flags & BR_HAIRPIN_MODE)
|
||||
+ && (skb->dev->ieee80211_ptr != NULL || !is_multicast_ether_addr(eth_hdr(skb)->h_dest)))
|
||||
+ || (skb->dev != p->dev)) &&
|
||||
+ br_allowed_egress(vg, skb) && (p->state == BR_STATE_FORWARDING) &&
|
||||
+ nbp_switchdev_allowed_egress(p, skb) &&
|
||||
+ !br_skb_isolated(p, skb);
|
||||
}
|
||||
|
||||
int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
@@ -0,0 +1,16 @@
|
||||
--- a/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
|
||||
+++ b/arch/arm/boot/dts/qcom/qcom-ipq8064.dtsi
|
||||
@@ -917,12 +917,10 @@
|
||||
qcom,vlan-enabled;
|
||||
qcom,wlan-dataplane-offload-enabled;
|
||||
qcom,wlanredirect-enabled;
|
||||
- qcom,pxvlan-enabled;
|
||||
qcom,vxlan-enabled;
|
||||
qcom,match-enabled;
|
||||
qcom,mirror-enabled;
|
||||
- qcom,rmnet-enabled;
|
||||
- qcom,clmap-enabled;
|
||||
+ qcom,tstamp-enabled;
|
||||
};
|
||||
|
||||
nss1: nss@40800000 {
|
||||
Reference in New Issue
Block a user