diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 0a8c775a4..622d1b844 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .41 -LINUX_KERNEL_HASH-5.15.41 = 3c7cb1fc3b029b1b765a33af9608b6f18f734246050640def019ee4c4ad6591e +LINUX_VERSION-5.15 = .42 +LINUX_KERNEL_HASH-5.15.42 = 5ecd47a9f663368f005f74d24c8de4ffd93007b675ddf342e2c6db956bf82560 diff --git a/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch b/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch index 9a6b802fd..19ec9d940 100644 --- a/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch +++ b/target/linux/generic/backport-5.15/343-netfilter-nft_flow_offload-handle-netdevice-events-f.patch @@ -10,7 +10,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c -@@ -646,13 +646,41 @@ void nf_flow_table_free(struct nf_flowta +@@ -608,13 +608,41 @@ void nf_flow_table_free(struct nf_flowta } EXPORT_SYMBOL_GPL(nf_flow_table_free); @@ -55,7 +55,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c -@@ -438,47 +438,14 @@ static struct nft_expr_type nft_flow_off +@@ -444,47 +444,14 @@ static struct nft_expr_type nft_flow_off .owner = THIS_MODULE, }; diff --git a/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch b/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch index 2554d6132..b25d0c32a 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0007-PCI-aardvark-Mask-all-interrupts-when-unbinding-driv.patch @@ -18,9 +18,9 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1878,6 +1878,27 @@ static int advk_pcie_remove(struct platf - /* Remove IRQ handler */ - irq_set_chained_handler_and_data(pcie->irq, NULL, NULL); +@@ -1874,6 +1874,27 @@ static int advk_pcie_remove(struct platf + advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG); + advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG); + /* Disable MSI */ + val = advk_readl(pcie, PCIE_CORE_CTRL2_REG); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch b/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch index bec863209..37a301cc7 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0008-PCI-aardvark-Fix-memory-leak-in-driver-unbind.patch @@ -21,7 +21,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1916,6 +1916,9 @@ static int advk_pcie_remove(struct platf +@@ -1912,6 +1912,9 @@ static int advk_pcie_remove(struct platf val &= ~LINK_TRAINING_EN; advk_writel(pcie, val, PCIE_CORE_CTRL0_REG); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch b/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch index 58aa31b8a..45df69ed7 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0009-PCI-aardvark-Assert-PERST-when-unbinding-driver.patch @@ -20,7 +20,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1919,6 +1919,10 @@ static int advk_pcie_remove(struct platf +@@ -1915,6 +1915,10 @@ static int advk_pcie_remove(struct platf /* Free config space for emulated root bridge */ pci_bridge_emul_cleanup(&pcie->bridge); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch b/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch index 47da52290..f60a0f2f1 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0010-PCI-aardvark-Disable-link-training-when-unbinding-dr.patch @@ -20,7 +20,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1923,6 +1923,11 @@ static int advk_pcie_remove(struct platf +@@ -1919,6 +1919,11 @@ static int advk_pcie_remove(struct platf if (pcie->reset_gpio) gpiod_set_value_cansleep(pcie->reset_gpio, 1); diff --git a/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch b/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch index 3fc68e9fa..b49b8a26c 100644 --- a/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch +++ b/target/linux/generic/backport-5.15/850-v5.17-0011-PCI-aardvark-Disable-common-PHY-when-unbinding-drive.patch @@ -18,7 +18,7 @@ Signed-off-by: Lorenzo Pieralisi --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1640,6 +1640,9 @@ static int advk_pcie_enable_phy(struct a +@@ -1634,6 +1634,9 @@ static int advk_pcie_enable_phy(struct a return ret; } diff --git a/target/linux/generic/hack-5.15/600-bridge_offload.patch b/target/linux/generic/hack-5.15/600-bridge_offload.patch index c7942a0ae..f2636a82e 100644 --- a/target/linux/generic/hack-5.15/600-bridge_offload.patch +++ b/target/linux/generic/hack-5.15/600-bridge_offload.patch @@ -154,7 +154,7 @@ static int br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) -@@ -164,6 +165,7 @@ int br_handle_frame_finish(struct net *n +@@ -171,6 +172,7 @@ int br_handle_frame_finish(struct net *n dst->used = now; br_forward(dst->dst, skb, local_rcv, false); } else { @@ -162,7 +162,7 @@ if (!mcast_hit) br_flood(br, skb, pkt_type, local_rcv, false); else -@@ -297,6 +299,9 @@ static rx_handler_result_t br_handle_fra +@@ -304,6 +306,9 @@ static rx_handler_result_t br_handle_fra memset(skb->cb, 0, sizeof(struct br_input_skb_cb)); p = br_port_get_rcu(skb->dev); diff --git a/target/linux/generic/hack-5.15/640-bridge-only-accept-EAP-locally.patch b/target/linux/generic/hack-5.15/640-bridge-only-accept-EAP-locally.patch index 543ebfd10..7ae96b43d 100644 --- a/target/linux/generic/hack-5.15/640-bridge-only-accept-EAP-locally.patch +++ b/target/linux/generic/hack-5.15/640-bridge-only-accept-EAP-locally.patch @@ -12,7 +12,7 @@ Signed-off-by: Etienne Champetier --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -109,10 +109,14 @@ int br_handle_frame_finish(struct net *n +@@ -116,10 +116,14 @@ int br_handle_frame_finish(struct net *n } } diff --git a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index a70d14b27..58510a5f4 100644 --- a/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch +++ b/target/linux/generic/hack-5.15/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o --- /dev/null +++ b/net/netfilter/xt_FLOWOFFLOAD.c -@@ -0,0 +1,657 @@ +@@ -0,0 +1,694 @@ +/* + * Copyright (C) 2018-2021 Felix Fietkau + * @@ -110,6 +110,7 @@ Signed-off-by: Felix Fietkau +#include +#include +#include ++#include +#include +#include +#include @@ -130,6 +131,21 @@ Signed-off-by: Felix Fietkau + struct delayed_work work; +}; + ++struct nf_forward_info { ++ const struct net_device *indev; ++ const struct net_device *outdev; ++ const struct net_device *hw_outdev; ++ struct id { ++ __u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; ++ u8 ingress_vlans; ++ u8 h_source[ETH_ALEN]; ++ u8 h_dest[ETH_ALEN]; ++ enum flow_offload_xmit_type xmit_type; ++}; ++ +static DEFINE_SPINLOCK(hooks_lock); + +struct xt_flowoffload_table flowtable[2]; @@ -138,12 +154,23 @@ Signed-off-by: Felix Fietkau +xt_flowoffload_net_hook(void *priv, struct sk_buff *skb, + const struct nf_hook_state *state) +{ -+ struct nf_flowtable *ft = priv; -+ -+ if (!atomic_read(&ft->rhashtable.nelems)) -+ return NF_ACCEPT; ++ struct vlan_ethhdr *veth; ++ __be16 proto; + + switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); ++ proto = veth->h_vlan_encapsulated_proto; ++ break; ++ case htons(ETH_P_PPP_SES): ++ proto = nf_flow_pppoe_proto(skb); ++ break; ++ default: ++ proto = skb->protocol; ++ break; ++ } ++ ++ switch (proto) { + case htons(ETH_P_IP): + return nf_flow_offload_ip_hook(priv, skb, state); + case htons(ETH_P_IPV6): @@ -262,7 +289,7 @@ Signed-off-by: Felix Fietkau +} + +static void -+xt_flowoffload_check_hook(struct flow_offload *flow, void *data) ++xt_flowoffload_check_hook(struct nf_flowtable *flowtable, struct flow_offload *flow, void *data) +{ + struct xt_flowoffload_table *table = data; + struct flow_offload_tuple *tuple0 = &flow->tuplehash[0].tuple; @@ -296,7 +323,7 @@ Signed-off-by: Felix Fietkau + spin_unlock_bh(&hooks_lock); + + err = nf_flow_table_iterate(&table->ft, xt_flowoffload_check_hook, -+ table); ++ NULL); + if (err && err != -EAGAIN) + goto out; + @@ -323,183 +350,209 @@ Signed-off-by: Felix Fietkau + return false; +} + -+static bool flow_is_valid_ether_device(const struct net_device *dev) ++static enum flow_offload_xmit_type nf_xmit_type(struct dst_entry *dst) ++{ ++ if (dst_xfrm(dst)) ++ return FLOW_OFFLOAD_XMIT_XFRM; ++ ++ return FLOW_OFFLOAD_XMIT_NEIGH; ++} ++ ++static void nf_default_forward_path(struct nf_flow_route *route, ++ struct dst_entry *dst_cache, ++ enum ip_conntrack_dir dir, ++ struct net_device **dev) ++{ ++ dev[!dir] = dst_cache->dev; ++ route->tuple[!dir].in.ifindex = dst_cache->dev->ifindex; ++ route->tuple[dir].dst = dst_cache; ++ route->tuple[dir].xmit_type = nf_xmit_type(dst_cache); ++} ++ ++static bool nf_is_valid_ether_device(const struct net_device *dev) +{ + if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || + dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) -+ return true; ++ return false; + + return true; +} + -+static void -+xt_flowoffload_route_check_path(struct nf_flow_route *route, -+ const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ struct net_device **out_dev) ++static void nf_dev_path_info(const struct net_device_path_stack *stack, ++ struct nf_forward_info *info, ++ unsigned char *ha) +{ -+ const struct dst_entry *dst = route->tuple[dir].dst; -+ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; -+ struct net_device_path_stack stack; -+ enum net_device_path_type prev_type; -+ struct net_device *dev = dst->dev; -+ struct neighbour *n; -+ bool last = false; -+ u8 nud_state; ++ const struct net_device_path *path; + int i; + -+ route->tuple[!dir].in.ifindex = dev->ifindex; -+ route->tuple[dir].out.ifindex = dev->ifindex; -+ -+ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM) -+ return; -+ -+ -+ -+ -+ -+ -+ n = dst_neigh_lookup(dst, daddr); -+ if (!n) -+ return; -+ -+ read_lock_bh(&n->lock); -+ nud_state = n->nud_state; -+ memcpy(route->tuple[dir].out.h_dest, n->ha, ETH_ALEN); -+ read_unlock_bh(&n->lock); -+ neigh_release(n); -+ -+ if (!(nud_state & NUD_VALID)) -+ return; -+ -+ if (dev_fill_forward_path(dev, route->tuple[dir].out.h_dest, &stack) || -+ !stack.num_paths) -+ return; -+ -+ prev_type = DEV_PATH_ETHERNET; -+ for (i = 0; i <= stack.num_paths; i++) { -+ const struct net_device_path *path = &stack.path[i]; -+ int n_encaps = route->tuple[!dir].in.num_encaps; -+ -+ dev = (struct net_device *)path->dev; -+ if (flow_is_valid_ether_device(dev)) { -+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) { -+ memcpy(route->tuple[dir].out.h_source, -+ dev->dev_addr, ETH_ALEN); -+ route->tuple[dir].out.ifindex = dev->ifindex; -+ } -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; -+ } ++ memcpy(info->h_dest, ha, ETH_ALEN); + ++ for (i = 0; i < stack->num_paths; i++) { ++ path = &stack->path[i]; + switch (path->type) { -+ case DEV_PATH_PPPOE: ++ case DEV_PATH_ETHERNET: ++ case DEV_PATH_DSA: + case DEV_PATH_VLAN: -+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || -+ i == stack.num_paths) { -+ last = true; ++ case DEV_PATH_PPPOE: ++ info->indev = path->dev; ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); ++ ++ if (path->type == DEV_PATH_ETHERNET) ++ break; ++ if (path->type == DEV_PATH_DSA) { ++ i = stack->num_paths; + break; + } + -+ route->tuple[!dir].in.num_encaps++; -+ route->tuple[!dir].in.encap[n_encaps].id = path->encap.id; -+ route->tuple[!dir].in.encap[n_encaps].proto = path->encap.proto; ++ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ ++ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { ++ info->indev = NULL; ++ break; ++ } ++ if (!info->outdev) ++ info->outdev = path->dev; ++ info->encap[info->num_encaps].id = path->encap.id; ++ info->encap[info->num_encaps].proto = path->encap.proto; ++ info->num_encaps++; + if (path->type == DEV_PATH_PPPOE) -+ memcpy(route->tuple[dir].out.h_dest, -+ path->encap.h_dest, ETH_ALEN); ++ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); + break; + case DEV_PATH_BRIDGE: -+ switch (path->bridge.vlan_mode) { -+ case DEV_PATH_BR_VLAN_TAG: -+ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || -+ i == stack.num_paths) { -+ last = true; -+ break; -+ } ++ if (is_zero_ether_addr(info->h_source)) ++ memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + -+ route->tuple[!dir].in.num_encaps++; -+ route->tuple[!dir].in.encap[n_encaps].id = -+ path->bridge.vlan_id; -+ route->tuple[!dir].in.encap[n_encaps].proto = -+ path->bridge.vlan_proto; ++ switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ info->ingress_vlans |= BIT(info->num_encaps - 1); ++ break; ++ case DEV_PATH_BR_VLAN_TAG: ++ info->encap[info->num_encaps].id = path->bridge.vlan_id; ++ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; ++ info->num_encaps++; + break; + case DEV_PATH_BR_VLAN_UNTAG: -+ route->tuple[!dir].in.num_encaps--; -+ break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: -+ route->tuple[!dir].in.ingress_vlans |= BIT(n_encaps - 1); ++ info->num_encaps--; + break; + case DEV_PATH_BR_VLAN_KEEP: + break; + } + break; + default: -+ last = true; ++ info->indev = NULL; + break; + } -+ -+ if (last) -+ break; + } ++ if (!info->outdev) ++ info->outdev = info->indev; + -+ *out_dev = dev; -+ route->tuple[dir].out.hw_ifindex = dev->ifindex; -+ route->tuple[!dir].in.ifindex = dev->ifindex; ++ info->hw_outdev = info->indev; ++ ++ if (nf_is_valid_ether_device(info->indev)) ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; +} + -+static int -+xt_flowoffload_route_dir(struct nf_flow_route *route, const struct nf_conn *ct, -+ enum ip_conntrack_dir dir, -+ const struct xt_action_param *par, int ifindex) ++static int nf_dev_fill_forward_path(const struct nf_flow_route *route, ++ const struct dst_entry *dst_cache, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, u8 *ha, ++ struct net_device_path_stack *stack) +{ -+ struct dst_entry *dst = NULL; -+ struct flowi fl; ++ const void *daddr = &ct->tuplehash[!dir].tuple.src.u3; ++ struct net_device *dev = dst_cache->dev; ++ struct neighbour *n; ++ u8 nud_state; + -+ memset(&fl, 0, sizeof(fl)); -+ switch (xt_family(par)) { -+ case NFPROTO_IPV4: -+ fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.src.u3.ip; -+ fl.u.ip4.flowi4_oif = ifindex; -+ break; -+ case NFPROTO_IPV6: -+ fl.u.ip6.saddr = ct->tuplehash[!dir].tuple.dst.u3.in6; -+ fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.src.u3.in6; -+ fl.u.ip6.flowi6_oif = ifindex; -+ break; ++ if (!nf_is_valid_ether_device(dev)) ++ goto out; ++ ++ n = dst_neigh_lookup(dst_cache, daddr); ++ if (!n) ++ return -1; ++ ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ ether_addr_copy(ha, n->ha); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); ++ ++ if (!(nud_state & NUD_VALID)) ++ return -1; ++ ++out: ++ return dev_fill_forward_path(dev, ha, stack); ++} ++ ++static void nf_dev_forward_path(struct nf_flow_route *route, ++ const struct nf_conn *ct, ++ enum ip_conntrack_dir dir, ++ struct net_device **devs) ++{ ++ const struct dst_entry *dst = route->tuple[dir].dst; ++ struct net_device_path_stack stack; ++ struct nf_forward_info info = {}; ++ unsigned char ha[ETH_ALEN]; ++ int i; ++ ++ if (nf_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) ++ nf_dev_path_info(&stack, &info, ha); ++ ++ devs[!dir] = (struct net_device *)info.indev; ++ if (!info.indev) ++ return; ++ ++ route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ for (i = 0; i < info.num_encaps; i++) { ++ route->tuple[!dir].in.encap[i].id = info.encap[i].id; ++ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; + } ++ route->tuple[!dir].in.num_encaps = info.num_encaps; ++ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; + -+ nf_route(xt_net(par), &dst, &fl, false, xt_family(par)); -+ if (!dst) -+ return -ENOENT; -+ -+ route->tuple[dir].dst = dst; -+ if (dst_xfrm(dst)) -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_XFRM; -+ else -+ route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_NEIGH; -+ -+ return 0; ++ if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { ++ memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); ++ memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); ++ route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; ++ route->tuple[dir].xmit_type = info.xmit_type; ++ } +} + +static int +xt_flowoffload_route(struct sk_buff *skb, const struct nf_conn *ct, + const struct xt_action_param *par, + struct nf_flow_route *route, enum ip_conntrack_dir dir, -+ struct net_device **dev) ++ struct net_device **devs) +{ -+ int ret; ++ struct dst_entry *this_dst = skb_dst(skb); ++ struct dst_entry *other_dst = NULL; ++ struct flowi fl; + -+ ret = xt_flowoffload_route_dir(route, ct, dir, par, -+ dev[dir]->ifindex); -+ if (ret) -+ return ret; ++ memset(&fl, 0, sizeof(fl)); ++ switch (xt_family(par)) { ++ case NFPROTO_IPV4: ++ fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip; ++ fl.u.ip4.flowi4_oif = xt_in(par)->ifindex; ++ break; ++ case NFPROTO_IPV6: ++ fl.u.ip6.saddr = ct->tuplehash[!dir].tuple.dst.u3.in6; ++ fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6; ++ fl.u.ip6.flowi6_oif = xt_in(par)->ifindex; ++ break; ++ } + -+ ret = xt_flowoffload_route_dir(route, ct, !dir, par, -+ dev[!dir]->ifindex); -+ if (ret) -+ return ret; ++ nf_route(xt_net(par), &other_dst, &fl, false, xt_family(par)); ++ if (!other_dst) ++ return -ENOENT; + -+ xt_flowoffload_route_check_path(route, ct, dir, &dev[!dir]); -+ xt_flowoffload_route_check_path(route, ct, !dir, &dev[dir]); ++ nf_default_forward_path(route, this_dst, dir, devs); ++ nf_default_forward_path(route, other_dst, !dir, devs); ++ ++ if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH && ++ route->tuple[!dir].xmit_type == FLOW_OFFLOAD_XMIT_NEIGH) { ++ nf_dev_forward_path(route, ct, dir, devs); ++ nf_dev_forward_path(route, ct, !dir, devs); ++ } + + return 0; +} @@ -542,7 +595,7 @@ Signed-off-by: Felix Fietkau + } + + if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) || -+ ct->status & IPS_SEQ_ADJUST) ++ ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH)) + return XT_CONTINUE; + + if (!nf_ct_is_confirmed(ct)) @@ -586,7 +639,6 @@ Signed-off-by: Felix Fietkau + xt_flowoffload_check_device(table, devs[0]); + xt_flowoffload_check_device(table, devs[1]); + -+ dst_release(route.tuple[dir].dst); + dst_release(route.tuple[!dir].dst); + + return XT_CONTINUE; @@ -594,7 +646,6 @@ Signed-off-by: Felix Fietkau +err_flow_add: + flow_offload_free(flow); +err_flow_alloc: -+ dst_release(route.tuple[dir].dst); + dst_release(route.tuple[!dir].dst); +err_flow_route: + clear_bit(IPS_OFFLOAD_BIT, &ct->status); @@ -661,20 +712,6 @@ Signed-off-by: Felix Fietkau + .notifier_call = flow_offload_netdev_event, +}; + -+static unsigned int -+nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, -+ const struct nf_hook_state *state) -+{ -+ switch (skb->protocol) { -+ case htons(ETH_P_IP): -+ return nf_flow_offload_ip_hook(priv, skb, state); -+ case htons(ETH_P_IPV6): -+ return nf_flow_offload_ipv6_hook(priv, skb, state); -+ } -+ -+ return NF_ACCEPT; -+} -+ +static int nf_flow_rule_route_inet(struct net *net, + const struct flow_offload *flow, + enum flow_offload_tuple_dir dir, @@ -704,7 +741,7 @@ Signed-off-by: Felix Fietkau + .setup = nf_flow_table_offload_setup, + .action = nf_flow_rule_route_inet, + .free = nf_flow_table_free, -+ .hook = nf_flow_offload_inet_hook, ++ .hook = xt_flowoffload_net_hook, + .owner = THIS_MODULE, +}; + @@ -766,23 +803,23 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -397,8 +396,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -380,8 +379,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); -static int -nf_flow_table_iterate(struct nf_flowtable *flow_table, +int nf_flow_table_iterate(struct nf_flowtable *flow_table, - void (*iter)(struct flow_offload *flow, void *data), + void (*iter)(struct nf_flowtable *flowtable, + struct flow_offload *flow, void *data), void *data) - { -@@ -430,6 +428,7 @@ nf_flow_table_iterate(struct nf_flowtabl - - return err; +@@ -435,6 +433,7 @@ static void nf_flow_offload_gc_step(stru + nf_flow_offload_stats(flow_table, flow); + } } +EXPORT_SYMBOL_GPL(nf_flow_table_iterate); - static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple) + static void nf_flow_offload_work_gc(struct work_struct *work) { --- /dev/null +++ b/include/uapi/linux/netfilter/xt_FLOWOFFLOAD.h @@ -806,14 +843,15 @@ Signed-off-by: Felix Fietkau +#endif /* _XT_FLOWOFFLOAD_H */ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -275,6 +275,10 @@ void nf_flow_table_free(struct nf_flowta +@@ -275,6 +275,11 @@ void nf_flow_table_free(struct nf_flowta void flow_offload_teardown(struct flow_offload *flow); +int nf_flow_table_iterate(struct nf_flowtable *flow_table, -+ void (*iter)(struct flow_offload *flow, void *data), -+ void *data); ++ void (*iter)(struct nf_flowtable *flowtable, ++ struct flow_offload *flow, void *data), ++ void *data); + void nf_flow_snat_port(const struct flow_offload *flow, struct sk_buff *skb, unsigned int thoff, - u8 protocol, enum flow_offload_tuple_dir dir); + u8 protocol, enum flow_offload_tuple_dir dir); \ No newline at end of file diff --git a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch index 2531e32ff..1f4d2fd39 100644 --- a/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch +++ b/target/linux/generic/hack-5.15/904-debloat_dma_buf.patch @@ -63,7 +63,7 @@ Signed-off-by: Felix Fietkau +dma-shared-buffer-objs := $(dma-buf-objs-y) --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c -@@ -1498,4 +1498,5 @@ static void __exit dma_buf_deinit(void) +@@ -1506,4 +1506,5 @@ static void __exit dma_buf_deinit(void) kern_unmount(dma_buf_mnt); dma_buf_uninit_sysfs_statistics(); } diff --git a/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch b/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch index 2b9570e9a..9968a7969 100644 --- a/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch +++ b/target/linux/generic/pending-5.15/150-bridge_allow_receiption_on_disabled_port.patch @@ -15,7 +15,7 @@ Signed-off-by: Felix Fietkau --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -197,6 +197,9 @@ static void __br_handle_local_finish(str +@@ -204,6 +204,9 @@ static void __br_handle_local_finish(str /* note: already called with rcu_read_lock */ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_buff *skb) { @@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau __br_handle_local_finish(skb); /* return 1 to signal the okfn() was called so it's ok to use the skb */ -@@ -362,6 +365,17 @@ static rx_handler_result_t br_handle_fra +@@ -369,6 +372,17 @@ static rx_handler_result_t br_handle_fra forward: switch (p->state) { diff --git a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch index 84a3ee8e6..2a2ca7f1f 100644 --- a/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch +++ b/target/linux/generic/pending-5.15/710-bridge-add-knob-for-filtering-rx-tx-BPDU-pack.patch @@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau if (!(p->flags & BR_BCAST_FLOOD) && skb->dev != br->dev) --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c -@@ -319,6 +319,8 @@ static rx_handler_result_t br_handle_fra +@@ -326,6 +326,8 @@ static rx_handler_result_t br_handle_fra fwd_mask |= p->group_fwd_mask; switch (dest[5]) { case 0x00: /* Bridge Group Address */ diff --git a/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch b/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch index 12ded91ca..2c5299673 100644 --- a/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch +++ b/target/linux/generic/pending-5.15/850-0016-PCI-aardvark-Add-support-for-PME-interrupts.patch @@ -25,7 +25,7 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1554,6 +1554,22 @@ static void advk_pcie_handle_int(struct +@@ -1553,6 +1553,22 @@ static void advk_pcie_handle_int(struct dev_err_ratelimited(&pcie->pdev->dev, "unhandled ERR IRQ\n"); } diff --git a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch index 96a55ba31..de28ebe73 100644 --- a/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch +++ b/target/linux/generic/pending-5.15/850-0023-PCI-aardvark-Make-main-irq_chip-structure-a-static-d.patch @@ -33,15 +33,15 @@ Signed-off-by: Marek Behún --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -275,7 +275,6 @@ struct advk_pcie { - int irq; +@@ -274,7 +274,6 @@ struct advk_pcie { + u8 wins_count; struct irq_domain *rp_irq_domain; struct irq_domain *irq_domain; - struct irq_chip irq_chip; raw_spinlock_t irq_lock; struct irq_domain *msi_domain; struct irq_domain *msi_inner_domain; -@@ -1331,14 +1330,19 @@ static void advk_pcie_irq_unmask(struct +@@ -1330,14 +1329,19 @@ static void advk_pcie_irq_unmask(struct raw_spin_unlock_irqrestore(&pcie->irq_lock, flags); } @@ -63,7 +63,7 @@ Signed-off-by: Marek Behún irq_set_chip_data(virq, pcie); return 0; -@@ -1397,7 +1401,6 @@ static int advk_pcie_init_irq_domain(str +@@ -1396,7 +1400,6 @@ static int advk_pcie_init_irq_domain(str struct device *dev = &pcie->pdev->dev; struct device_node *node = dev->of_node; struct device_node *pcie_intc_node; @@ -71,7 +71,7 @@ Signed-off-by: Marek Behún int ret = 0; raw_spin_lock_init(&pcie->irq_lock); -@@ -1408,28 +1411,14 @@ static int advk_pcie_init_irq_domain(str +@@ -1407,28 +1410,14 @@ static int advk_pcie_init_irq_domain(str return -ENODEV; } diff --git a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch index be901609c..80ec71f74 100644 --- a/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch +++ b/target/linux/generic/pending-5.15/851-0006-Revert-PCI-aardvark-Fix-initialization-with-old-Marv.patch @@ -23,7 +23,7 @@ Acked-by: Miquel Raynal --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c -@@ -1638,9 +1638,7 @@ static int advk_pcie_enable_phy(struct a +@@ -1632,9 +1632,7 @@ static int advk_pcie_enable_phy(struct a } ret = phy_power_on(pcie->phy);