-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'net-move-more-duplicate-code-of-ovs-and-tc-conntrack-in…
…to-nf_conntrack_ovs' Xin Long says: ==================== net: move more duplicate code of ovs and tc conntrack into nf_conntrack_ovs We've moved some duplicate code into nf_nat_ovs in: "net: eliminate the duplicate code in the ct nat functions of ovs and tc" This patchset addresses more code duplication in the conntrack of ovs and tc then creates nf_conntrack_ovs for them, and four functions will be extracted and moved into it: nf_ct_handle_fragments() nf_ct_skb_network_trim() nf_ct_helper() nf_ct_add_helper() ==================== Link: https://lore.kernel.org/r/cover.1675810210.git.lucien.xin@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
- Loading branch information
Showing
9 changed files
with
207 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
/* Support ct functions for openvswitch and used by OVS and TC conntrack. */ | ||
|
||
#include <net/netfilter/nf_conntrack_helper.h> | ||
#include <net/netfilter/nf_conntrack_seqadj.h> | ||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h> | ||
#include <net/ipv6_frag.h> | ||
#include <net/ip.h> | ||
|
||
/* 'skb' should already be pulled to nh_ofs. */ | ||
int nf_ct_helper(struct sk_buff *skb, struct nf_conn *ct, | ||
enum ip_conntrack_info ctinfo, u16 proto) | ||
{ | ||
const struct nf_conntrack_helper *helper; | ||
const struct nf_conn_help *help; | ||
unsigned int protoff; | ||
int err; | ||
|
||
if (ctinfo == IP_CT_RELATED_REPLY) | ||
return NF_ACCEPT; | ||
|
||
help = nfct_help(ct); | ||
if (!help) | ||
return NF_ACCEPT; | ||
|
||
helper = rcu_dereference(help->helper); | ||
if (!helper) | ||
return NF_ACCEPT; | ||
|
||
if (helper->tuple.src.l3num != NFPROTO_UNSPEC && | ||
helper->tuple.src.l3num != proto) | ||
return NF_ACCEPT; | ||
|
||
switch (proto) { | ||
case NFPROTO_IPV4: | ||
protoff = ip_hdrlen(skb); | ||
proto = ip_hdr(skb)->protocol; | ||
break; | ||
case NFPROTO_IPV6: { | ||
u8 nexthdr = ipv6_hdr(skb)->nexthdr; | ||
__be16 frag_off; | ||
int ofs; | ||
|
||
ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, | ||
&frag_off); | ||
if (ofs < 0 || (frag_off & htons(~0x7)) != 0) { | ||
pr_debug("proto header not found\n"); | ||
return NF_ACCEPT; | ||
} | ||
protoff = ofs; | ||
proto = nexthdr; | ||
break; | ||
} | ||
default: | ||
WARN_ONCE(1, "helper invoked on non-IP family!"); | ||
return NF_DROP; | ||
} | ||
|
||
if (helper->tuple.dst.protonum != proto) | ||
return NF_ACCEPT; | ||
|
||
err = helper->help(skb, protoff, ct, ctinfo); | ||
if (err != NF_ACCEPT) | ||
return err; | ||
|
||
/* Adjust seqs after helper. This is needed due to some helpers (e.g., | ||
* FTP with NAT) adusting the TCP payload size when mangling IP | ||
* addresses and/or port numbers in the text-based control connection. | ||
*/ | ||
if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && | ||
!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) | ||
return NF_DROP; | ||
return NF_ACCEPT; | ||
} | ||
EXPORT_SYMBOL_GPL(nf_ct_helper); | ||
|
||
int nf_ct_add_helper(struct nf_conn *ct, const char *name, u8 family, | ||
u8 proto, bool nat, struct nf_conntrack_helper **hp) | ||
{ | ||
struct nf_conntrack_helper *helper; | ||
struct nf_conn_help *help; | ||
int ret = 0; | ||
|
||
helper = nf_conntrack_helper_try_module_get(name, family, proto); | ||
if (!helper) | ||
return -EINVAL; | ||
|
||
help = nf_ct_helper_ext_add(ct, GFP_KERNEL); | ||
if (!help) { | ||
nf_conntrack_helper_put(helper); | ||
return -ENOMEM; | ||
} | ||
#if IS_ENABLED(CONFIG_NF_NAT) | ||
if (nat) { | ||
ret = nf_nat_helper_try_module_get(name, family, proto); | ||
if (ret) { | ||
nf_conntrack_helper_put(helper); | ||
return ret; | ||
} | ||
} | ||
#endif | ||
rcu_assign_pointer(help->helper, helper); | ||
*hp = helper; | ||
return ret; | ||
} | ||
EXPORT_SYMBOL_GPL(nf_ct_add_helper); | ||
|
||
/* Trim the skb to the length specified by the IP/IPv6 header, | ||
* removing any trailing lower-layer padding. This prepares the skb | ||
* for higher-layer processing that assumes skb->len excludes padding | ||
* (such as nf_ip_checksum). The caller needs to pull the skb to the | ||
* network header, and ensure ip_hdr/ipv6_hdr points to valid data. | ||
*/ | ||
int nf_ct_skb_network_trim(struct sk_buff *skb, int family) | ||
{ | ||
unsigned int len; | ||
|
||
switch (family) { | ||
case NFPROTO_IPV4: | ||
len = skb_ip_totlen(skb); | ||
break; | ||
case NFPROTO_IPV6: | ||
len = sizeof(struct ipv6hdr) | ||
+ ntohs(ipv6_hdr(skb)->payload_len); | ||
break; | ||
default: | ||
len = skb->len; | ||
} | ||
|
||
return pskb_trim_rcsum(skb, len); | ||
} | ||
EXPORT_SYMBOL_GPL(nf_ct_skb_network_trim); | ||
|
||
/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero | ||
* value if 'skb' is freed. | ||
*/ | ||
int nf_ct_handle_fragments(struct net *net, struct sk_buff *skb, | ||
u16 zone, u8 family, u8 *proto, u16 *mru) | ||
{ | ||
int err; | ||
|
||
if (family == NFPROTO_IPV4) { | ||
enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone; | ||
|
||
memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | ||
local_bh_disable(); | ||
err = ip_defrag(net, skb, user); | ||
local_bh_enable(); | ||
if (err) | ||
return err; | ||
|
||
*mru = IPCB(skb)->frag_max_size; | ||
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) | ||
} else if (family == NFPROTO_IPV6) { | ||
enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone; | ||
|
||
memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm)); | ||
err = nf_ct_frag6_gather(net, skb, user); | ||
if (err) { | ||
if (err != -EINPROGRESS) | ||
kfree_skb(skb); | ||
return err; | ||
} | ||
|
||
*proto = ipv6_hdr(skb)->nexthdr; | ||
*mru = IP6CB(skb)->frag_max_size; | ||
#endif | ||
} else { | ||
kfree_skb(skb); | ||
return -EPFNOSUPPORT; | ||
} | ||
|
||
skb_clear_hash(skb); | ||
skb->ignore_df = 1; | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(nf_ct_handle_fragments); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.