From patchwork Thu Jul 29 15:22:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryoga Saito X-Patchwork-Id: 1511327 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=proelbtn.com header.i=contact@proelbtn.com header.a=rsa-sha256 header.s=default header.b=CGoSVsSq; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4GbDqb5310z9sRf for ; Fri, 30 Jul 2021 01:25:15 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238084AbhG2PZR (ORCPT ); Thu, 29 Jul 2021 11:25:17 -0400 Received: from sender4-of-o55.zoho.com ([136.143.188.55]:21534 "EHLO sender4-of-o55.zoho.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238036AbhG2PZP (ORCPT ); Thu, 29 Jul 2021 11:25:15 -0400 ARC-Seal: i=1; a=rsa-sha256; t=1627572165; cv=none; d=zohomail.com; s=zohoarc; b=jhkmqTRjGd52ZhLUQeqGsRGIg3/auTMUUdmKUQD2hPEEFMTu5Bt9nfyPlTtfKroJZGnVuTO02n8+snoHGdy8Hd9NZiTGsJB7FDuAWi6IR3lbTkXhzuRhVdIsQJIjePY1umXDyfPlL4tZUotApYBTV4Kar+D56jIL53Gms6t32TE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1627572165; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:To; bh=h32FgQR1FyHKdL2NEJQZPRS68BEOl1ffiItsfhciJvo=; b=lbbI45ftDqcCgPY1S19OsTgOFEjRIum8xIRMcCzwu9G/DvVka/1rNJdqGCUwzS0+6VJv0lvGo2JRB5PjDzdquz9XU/3i9i216gez4kjIF+zWU5gP21V+UogE6pBey3bpuVN3l4K29igSygevXELAYrY/YlPrJkH52QFfp0Rr6D8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=proelbtn.com; spf=pass smtp.mailfrom=contact@proelbtn.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1627572165; s=default; d=proelbtn.com; i=contact@proelbtn.com; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=h32FgQR1FyHKdL2NEJQZPRS68BEOl1ffiItsfhciJvo=; b=CGoSVsSqOB1sYGkAM/1vCqoUptXnbKoGdalsg11Jmse696ixUhZei9mJRtf1jN8X fvxGJo31IVyXLsfGmi0e1sReuZIaSoKIXf6bL9w8P7DtM4xys08jYUwNXnS2Rxa13yM K4jVrP6shRsWC0DmiDGJbzvmMq9AsnQ2M6xSeKX4= Received: from srv6.prochi.io (softbank060108183144.bbtec.net [60.108.183.144]) by mx.zohomail.com with SMTPS id 1627572164544562.4707704223355; Thu, 29 Jul 2021 08:22:44 -0700 (PDT) From: Ryoga Saito To: netfilter-devel@vger.kernel.org Cc: pablo@netfilter.org, stefano.salsano@uniroma2.it, andrea.mayer@uniroma2.it, davem@davemloft.net, kuba@kernel.org, yoshfuji@linux-ipv6.org, dsahern@kernel.org, Ryoga Saito Subject: [PATCH v3 1/2] netfilter: add new sysctl toggle for lightweight tunnel netfilter hooks Date: Thu, 29 Jul 2021 15:22:33 +0000 Message-Id: <7369c6af9a8190f08ede4e936b505b6eedc871a6.1627571302.git.contact@proelbtn.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-ZohoMailClient: External Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch introduces new sysctl toggle for enabling lightweight tunnel netfilter hooks. Signed-off-by: Ryoga Saito Reported-by: kernel test robot --- .../networking/nf_conntrack-sysctl.rst | 7 +++ include/net/lwtunnel.h | 2 + include/net/netfilter/nf_conntrack.h | 4 ++ net/core/lwtunnel.c | 3 ++ net/netfilter/Makefile | 2 +- net/netfilter/nf_conntrack_lwtunnel.c | 52 +++++++++++++++++++ net/netfilter/nf_conntrack_standalone.c | 8 +++ 7 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 net/netfilter/nf_conntrack_lwtunnel.c diff --git a/Documentation/networking/nf_conntrack-sysctl.rst b/Documentation/networking/nf_conntrack-sysctl.rst index d31ed6c1cb0d..5afa4603aa4b 100644 --- a/Documentation/networking/nf_conntrack-sysctl.rst +++ b/Documentation/networking/nf_conntrack-sysctl.rst @@ -30,6 +30,13 @@ nf_conntrack_checksum - BOOLEAN in INVALID state. If this is enabled, such packets will not be considered for connection tracking. +nf_conntrack_lwtunnel - BOOLEAN + - 0 - disabled (default) + - not 0 - enabled + + If this option is enabled, the lightweight tunnel netfilter hooks are + enabled. This option cannot be disabled once it is enabled. + nf_conntrack_count - INTEGER (read-only) Number of currently allocated flow entries. diff --git a/include/net/lwtunnel.h b/include/net/lwtunnel.h index 05cfd6ff6528..c6029f7eec14 100644 --- a/include/net/lwtunnel.h +++ b/include/net/lwtunnel.h @@ -51,6 +51,8 @@ struct lwtunnel_encap_ops { }; #ifdef CONFIG_LWTUNNEL +DECLARE_STATIC_KEY_FALSE(nf_ct_lwtunnel_enabled); + void lwtstate_free(struct lwtunnel_state *lws); static inline struct lwtunnel_state * diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index cc663c68ddc4..d2a74fc75346 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -360,4 +360,8 @@ static inline struct nf_conntrack_net *nf_ct_pernet(const struct net *net) #define MODULE_ALIAS_NFCT_HELPER(helper) \ MODULE_ALIAS("nfct-helper-" helper) +int nf_conntrack_lwtunnel_sysctl_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, + loff_t *ppos); + #endif /* _NF_CONNTRACK_H */ diff --git a/net/core/lwtunnel.c b/net/core/lwtunnel.c index 8ec7d13d2860..8be3274e30ec 100644 --- a/net/core/lwtunnel.c +++ b/net/core/lwtunnel.c @@ -23,6 +23,9 @@ #include #include +DEFINE_STATIC_KEY_FALSE(nf_ct_lwtunnel_enabled); +EXPORT_SYMBOL_GPL(nf_ct_lwtunnel_enabled); + #ifdef CONFIG_MODULES static const char *lwtunnel_encap_str(enum lwtunnel_encap_types encap_type) diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 049890e00a3d..dd784b872c61 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -4,7 +4,7 @@ netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o \ nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o \ nf_conntrack_proto_icmp.o \ - nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o + nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o nf_conntrack_lwtunnel.o nf_conntrack-$(subst m,y,$(CONFIG_IPV6)) += nf_conntrack_proto_icmpv6.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o diff --git a/net/netfilter/nf_conntrack_lwtunnel.c b/net/netfilter/nf_conntrack_lwtunnel.c new file mode 100644 index 000000000000..cddbf8c5883a --- /dev/null +++ b/net/netfilter/nf_conntrack_lwtunnel.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +static inline int nf_conntrack_lwtunnel_get(void) +{ + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return 1; + else + return 0; +} + +static inline int nf_conntrack_lwtunnel_set(int enable) +{ + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) { + if (!enable) + return -EPERM; + } else if (enable) { + static_branch_enable(&nf_ct_lwtunnel_enabled); + } + + return 0; +} + +int nf_conntrack_lwtunnel_sysctl_handler(struct ctl_table *table, int write, + void *buffer, size_t *lenp, + loff_t *ppos) +{ + int proc_nf_ct_lwtunnel_enabled = 0; + struct ctl_table tmp = { + .procname = table->procname, + .data = &proc_nf_ct_lwtunnel_enabled, + .maxlen = sizeof(int), + .mode = table->mode, + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }; + int ret; + + if (!write) + proc_nf_ct_lwtunnel_enabled = nf_conntrack_lwtunnel_get(); + + ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); + + if (write && ret == 0) + ret = nf_conntrack_lwtunnel_set(proc_nf_ct_lwtunnel_enabled); + + return ret; +} +EXPORT_SYMBOL_GPL(nf_conntrack_lwtunnel_sysctl_handler); \ No newline at end of file diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 214d9f9e499b..f20568496ef0 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -552,6 +552,7 @@ enum nf_ct_sysctl_index { NF_SYSCTL_CT_COUNT, NF_SYSCTL_CT_BUCKETS, NF_SYSCTL_CT_CHECKSUM, + NF_SYSCTL_CT_LWTUNNEL, NF_SYSCTL_CT_LOG_INVALID, NF_SYSCTL_CT_EXPECT_MAX, NF_SYSCTL_CT_ACCT, @@ -650,6 +651,13 @@ static struct ctl_table nf_ct_sysctl_table[] = { .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, }, + [NF_SYSCTL_CT_LWTUNNEL] = { + .procname = "nf_conntrack_lwtunnel", + .data = NULL, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = nf_conntrack_lwtunnel_sysctl_handler, + }, [NF_SYSCTL_CT_LOG_INVALID] = { .procname = "nf_conntrack_log_invalid", .data = &init_net.ct.sysctl_log_invalid, From patchwork Thu Jul 29 15:22:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryoga Saito X-Patchwork-Id: 1511329 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=proelbtn.com header.i=contact@proelbtn.com header.a=rsa-sha256 header.s=default header.b=PSVEaeZS; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4GbDrB10YCz9sRf for ; Fri, 30 Jul 2021 01:25:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237579AbhG2PZs (ORCPT ); Thu, 29 Jul 2021 11:25:48 -0400 Received: from sender4-of-o55.zoho.com ([136.143.188.55]:21545 "EHLO sender4-of-o55.zoho.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238036AbhG2PZn (ORCPT ); Thu, 29 Jul 2021 11:25:43 -0400 ARC-Seal: i=1; a=rsa-sha256; t=1627572167; cv=none; d=zohomail.com; s=zohoarc; b=YIg8dMYFGQz8/dVEU104OZPy3FbktVER0aWAqohjgcYacMsAFL9QzzrQ/3oPB7FSeO8pU3yJ3t+kL23zwgh+wAYE01FbeQ9KUc1jiwQvM1KTT6yZxW4LTVGR/ADD2oBi8yRFj1gPKbRGi0h8/6yIEshzGD0Ta3NCnqzWPcfPhLw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1627572167; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:To; bh=OwPo4qO/eS2F1SoQVwnwVxMDmLogfT1Y9LHgpA5fJNU=; b=HcO1DHH5HCvtHJIYwTFbLQIFkxxFa7ck9W1N69NnyBAt/ZzZwN7Dt0jcEJ3iN14S0V6w8pdpVSInZJuPBzSBA1wfwTcpVvQ+TEh79PZIS4/QhSu9XLHPvIfQ8N/sJhy1thKLRr4K+KPy3PQA2l7hrXzDG97GFPZuYzswWyLtkiM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass header.i=proelbtn.com; spf=pass smtp.mailfrom=contact@proelbtn.com; dmarc=pass header.from= DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1627572167; s=default; d=proelbtn.com; i=contact@proelbtn.com; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=OwPo4qO/eS2F1SoQVwnwVxMDmLogfT1Y9LHgpA5fJNU=; b=PSVEaeZSHOzCXlwChf493yCTXwGmPSs5p4uXdKvUkdD1iXKkso87Ln+qDzshw6GQ nx/3Rj7D1KLfKdSj1BWCjcLZZvCSOPISXYHBkIcU0AwyiDxR2d9Y8JTpoEhjVdag9xE R1I6tbbZVmbg7zIf8KJnu6lOE8F2rsYP1iNHyjZs= Received: from srv6.prochi.io (softbank060108183144.bbtec.net [60.108.183.144]) by mx.zohomail.com with SMTPS id 1627572166609948.5643607579253; Thu, 29 Jul 2021 08:22:46 -0700 (PDT) From: Ryoga Saito To: netfilter-devel@vger.kernel.org Cc: pablo@netfilter.org, stefano.salsano@uniroma2.it, andrea.mayer@uniroma2.it, davem@davemloft.net, kuba@kernel.org, yoshfuji@linux-ipv6.org, dsahern@kernel.org, Ryoga Saito Subject: [PATCH v3 2/2] netfilter: add netfilter hooks to SRv6 data plane Date: Thu, 29 Jul 2021 15:22:34 +0000 Message-Id: <1ced93af850ae362d3e79c489c7f4315d35d6c39.1627571302.git.contact@proelbtn.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-ZohoMailClient: External Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org This patch introduces netfilter hooks for solving the problem that conntrack couldn't record both inner flows and outer flows. Signed-off-by: Ryoga Saito --- net/ipv6/seg6_iptunnel.c | 68 +++++++++++++++++++++-- net/ipv6/seg6_local.c | 115 +++++++++++++++++++++++++++------------ 2 files changed, 141 insertions(+), 42 deletions(-) diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c index 897fa59c47de..77a2aafcb52f 100644 --- a/net/ipv6/seg6_iptunnel.c +++ b/net/ipv6/seg6_iptunnel.c @@ -26,6 +26,7 @@ #ifdef CONFIG_IPV6_SEG6_HMAC #include #endif +#include static size_t seg6_lwt_headroom(struct seg6_iptunnel_encap *tuninfo) { @@ -295,25 +296,33 @@ static int seg6_do_srh(struct sk_buff *skb) ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); skb_set_transport_header(skb, sizeof(struct ipv6hdr)); + nf_reset_ct(skb); return 0; } -static int seg6_input(struct sk_buff *skb) +static int seg6_input_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + return dst_input(skb); +} + +static int seg6_input_core(struct net *net, struct sock *sk, + struct sk_buff *skb) { struct dst_entry *orig_dst = skb_dst(skb); struct dst_entry *dst = NULL; - struct seg6_lwt *slwt; + struct seg6_lwt *slwt = NULL; int err; + slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); + err = seg6_do_srh(skb); if (unlikely(err)) { kfree_skb(skb); return err; } - slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate); - preempt_disable(); dst = dst_cache_get(&slwt->cache); preempt_enable(); @@ -337,10 +346,35 @@ static int seg6_input(struct sk_buff *skb) if (unlikely(err)) return err; - return dst_input(skb); + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, + dev_net(skb->dev), NULL, skb, NULL, + skb_dst(skb)->dev, seg6_input_finish); + + return seg6_input_finish(dev_net(skb->dev), NULL, skb); } -static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb) +static int seg6_input(struct sk_buff *skb) +{ + int proto; + + if (skb->protocol == htons(ETH_P_IPV6)) + proto = NFPROTO_IPV6; + else if (skb->protocol == htons(ETH_P_IP)) + proto = NFPROTO_IPV4; + else + return -EINVAL; + + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(proto, NF_INET_POST_ROUTING, dev_net(skb->dev), + NULL, skb, NULL, skb_dst(skb)->dev, + seg6_input_core); + + return seg6_input_core(dev_net(skb->dev), NULL, skb); +} + +static int seg6_output_core(struct net *net, struct sock *sk, + struct sk_buff *skb) { struct dst_entry *orig_dst = skb_dst(skb); struct dst_entry *dst = NULL; @@ -387,12 +421,34 @@ static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb) if (unlikely(err)) goto drop; + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb, + NULL, skb_dst(skb)->dev, dst_output); + return dst_output(net, sk, skb); drop: kfree_skb(skb); return err; } +static int seg6_output(struct net *net, struct sock *sk, struct sk_buff *skb) +{ + int proto; + + if (skb->protocol == htons(ETH_P_IPV6)) + proto = NFPROTO_IPV6; + else if (skb->protocol == htons(ETH_P_IP)) + proto = NFPROTO_IPV4; + else + return -EINVAL; + + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(proto, NF_INET_POST_ROUTING, net, sk, skb, NULL, + skb_dst(skb)->dev, seg6_output_core); + + return seg6_output_core(net, sk, skb); +} + static int seg6_build_state(struct net *net, struct nlattr *nla, unsigned int family, const void *cfg, struct lwtunnel_state **ts, diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c index 60bf3b877957..d883475be043 100644 --- a/net/ipv6/seg6_local.c +++ b/net/ipv6/seg6_local.c @@ -30,6 +30,7 @@ #include #include #include +#include #define SEG6_F_ATTR(i) BIT(i) @@ -413,12 +414,33 @@ static int input_action_end_dx2(struct sk_buff *skb, return -EINVAL; } +static int input_action_end_dx6_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + struct dst_entry *orig_dst = skb_dst(skb); + struct seg6_local_lwt *slwt = NULL; + struct in6_addr *nhaddr = NULL; + + slwt = seg6_local_lwtunnel(orig_dst->lwtstate); + + /* The inner packet is not associated to any local interface, + * so we do not call netif_rx(). + * + * If slwt->nh6 is set to ::, then lookup the nexthop for the + * inner packet's DA. Otherwise, use the specified nexthop. + */ + if (!ipv6_addr_any(&slwt->nh6)) + nhaddr = &slwt->nh6; + + seg6_lookup_nexthop(skb, nhaddr, 0); + + return dst_input(skb); +} + /* decapsulate and forward to specified nexthop */ static int input_action_end_dx6(struct sk_buff *skb, struct seg6_local_lwt *slwt) { - struct in6_addr *nhaddr = NULL; - /* this function accepts IPv6 encapsulated packets, with either * an SRH with SL=0, or no SRH. */ @@ -429,55 +451,64 @@ static int input_action_end_dx6(struct sk_buff *skb, if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto drop; - /* The inner packet is not associated to any local interface, - * so we do not call netif_rx(). - * - * If slwt->nh6 is set to ::, then lookup the nexthop for the - * inner packet's DA. Otherwise, use the specified nexthop. - */ - - if (!ipv6_addr_any(&slwt->nh6)) - nhaddr = &slwt->nh6; - skb_set_transport_header(skb, sizeof(struct ipv6hdr)); + nf_reset_ct(skb); - seg6_lookup_nexthop(skb, nhaddr, 0); + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, + dev_net(skb->dev), NULL, skb, NULL, + skb_dst(skb)->dev, input_action_end_dx6_finish); - return dst_input(skb); + return input_action_end_dx6_finish(dev_net(skb->dev), NULL, skb); drop: kfree_skb(skb); return -EINVAL; } -static int input_action_end_dx4(struct sk_buff *skb, - struct seg6_local_lwt *slwt) +static int input_action_end_dx4_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) { + struct dst_entry *orig_dst = skb_dst(skb); + struct seg6_local_lwt *slwt = NULL; struct iphdr *iph; __be32 nhaddr; int err; - if (!decap_and_validate(skb, IPPROTO_IPIP)) - goto drop; - - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - goto drop; - - skb->protocol = htons(ETH_P_IP); + slwt = seg6_local_lwtunnel(orig_dst->lwtstate); iph = ip_hdr(skb); - nhaddr = slwt->nh4.s_addr ?: iph->daddr; skb_dst_drop(skb); - skb_set_transport_header(skb, sizeof(struct iphdr)); - err = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev); - if (err) - goto drop; + if (err) { + kfree_skb(skb); + return -EINVAL; + } return dst_input(skb); +} +static int input_action_end_dx4(struct sk_buff *skb, + struct seg6_local_lwt *slwt) +{ + if (!decap_and_validate(skb, IPPROTO_IPIP)) + goto drop; + + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto drop; + + skb->protocol = htons(ETH_P_IP); + skb_set_transport_header(skb, sizeof(struct iphdr)); + nf_reset_ct(skb); + + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, + dev_net(skb->dev), NULL, skb, NULL, + skb_dst(skb)->dev, input_action_end_dx4_finish); + + return input_action_end_dx4_finish(dev_net(skb->dev), NULL, skb); drop: kfree_skb(skb); return -EINVAL; @@ -645,6 +676,7 @@ static struct sk_buff *end_dt_vrf_core(struct sk_buff *skb, skb_dst_drop(skb); skb_set_transport_header(skb, hdrlen); + nf_reset_ct(skb); return end_dt_vrf_rcv(skb, family, vrf); @@ -1078,22 +1110,18 @@ static void seg6_local_update_counters(struct seg6_local_lwt *slwt, u64_stats_update_end(&pcounters->syncp); } -static int seg6_local_input(struct sk_buff *skb) +static int seg6_local_input_core(struct net *net, struct sock *sk, + struct sk_buff *skb) { struct dst_entry *orig_dst = skb_dst(skb); + struct seg6_local_lwt *slwt = NULL; struct seg6_action_desc *desc; - struct seg6_local_lwt *slwt; unsigned int len = skb->len; int rc; - if (skb->protocol != htons(ETH_P_IPV6)) { - kfree_skb(skb); - return -EINVAL; - } - slwt = seg6_local_lwtunnel(orig_dst->lwtstate); - desc = slwt->desc; + desc = slwt->desc; rc = desc->input(skb, slwt); if (!seg6_lwtunnel_counters_enabled(slwt)) @@ -1104,6 +1132,21 @@ static int seg6_local_input(struct sk_buff *skb) return rc; } +static int seg6_local_input(struct sk_buff *skb) +{ + if (skb->protocol != htons(ETH_P_IPV6)) { + kfree_skb(skb); + return -EINVAL; + } + + if (static_branch_unlikely(&nf_ct_lwtunnel_enabled)) + return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, + dev_net(skb->dev), NULL, skb, skb->dev, NULL, + seg6_local_input_core); + + return seg6_local_input_core(dev_net(skb->dev), NULL, skb); +} + static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = { [SEG6_LOCAL_ACTION] = { .type = NLA_U32 }, [SEG6_LOCAL_SRH] = { .type = NLA_BINARY },