Merge git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following patchset contains Netfilter updates for net-next, misc
updates and fallout fixes from recent Florian's code rewritting (from
last pull request):

1) Use new flowi4_l3mdev field in ip_route_me_harder(), from Martin Willi.

2) Avoid unnecessary GC with a timestamp in conncount, from William Tu
   and Yifeng Sun.

3) Remove TCP conntrack debugging, from Florian Westphal.

4) Fix compilation warning in ctnetlink, from Florian.

* git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
  netfilter: ctnetlink: fix up for "netfilter: conntrack: remove unconfirmed list"
  netfilter: conntrack: remove pr_debug callsites from tcp tracker
  netfilter: nf_conncount: reduce unnecessary GC
  netfilter: Use l3mdev flow key when re-routing mangled packets
====================

Link: https://lore.kernel.org/r/20220519220206.722153-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2022-05-19 16:06:33 -07:00
commit 805cb5aadc
6 changed files with 20 additions and 52 deletions

View File

@ -10,6 +10,7 @@ struct nf_conncount_data;
struct nf_conncount_list { struct nf_conncount_list {
spinlock_t list_lock; spinlock_t list_lock;
u32 last_gc; /* jiffies at most recent gc */
struct list_head head; /* connections with the same filtering key */ struct list_head head; /* connections with the same filtering key */
unsigned int count; /* length of list */ unsigned int count; /* length of list */
}; };

View File

@ -45,8 +45,7 @@ int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, un
fl4.saddr = saddr; fl4.saddr = saddr;
fl4.flowi4_tos = RT_TOS(iph->tos); fl4.flowi4_tos = RT_TOS(iph->tos);
fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0; fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0;
if (!fl4.flowi4_oif) fl4.flowi4_l3mdev = l3mdev_master_ifindex(dev);
fl4.flowi4_oif = l3mdev_master_ifindex(dev);
fl4.flowi4_mark = skb->mark; fl4.flowi4_mark = skb->mark;
fl4.flowi4_flags = flags; fl4.flowi4_flags = flags;
fib4_rules_early_flow_dissect(net, skb, &fl4, &flkeys); fib4_rules_early_flow_dissect(net, skb, &fl4, &flkeys);

View File

@ -31,6 +31,7 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff
int strict = (ipv6_addr_type(&iph->daddr) & int strict = (ipv6_addr_type(&iph->daddr) &
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
struct flowi6 fl6 = { struct flowi6 fl6 = {
.flowi6_l3mdev = l3mdev_master_ifindex(dev),
.flowi6_mark = skb->mark, .flowi6_mark = skb->mark,
.flowi6_uid = sock_net_uid(net, sk), .flowi6_uid = sock_net_uid(net, sk),
.daddr = iph->daddr, .daddr = iph->daddr,
@ -42,8 +43,6 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff
fl6.flowi6_oif = sk->sk_bound_dev_if; fl6.flowi6_oif = sk->sk_bound_dev_if;
else if (strict) else if (strict)
fl6.flowi6_oif = dev->ifindex; fl6.flowi6_oif = dev->ifindex;
else
fl6.flowi6_oif = l3mdev_master_ifindex(dev);
fib6_rules_early_flow_dissect(net, skb, &fl6, &flkeys); fib6_rules_early_flow_dissect(net, skb, &fl6, &flkeys);
dst = ip6_route_output(net, sk, &fl6); dst = ip6_route_output(net, sk, &fl6);

View File

@ -132,6 +132,9 @@ static int __nf_conncount_add(struct net *net,
struct nf_conn *found_ct; struct nf_conn *found_ct;
unsigned int collect = 0; unsigned int collect = 0;
if (time_is_after_eq_jiffies((unsigned long)list->last_gc))
goto add_new_node;
/* check the saved connections */ /* check the saved connections */
list_for_each_entry_safe(conn, conn_n, &list->head, node) { list_for_each_entry_safe(conn, conn_n, &list->head, node) {
if (collect > CONNCOUNT_GC_MAX_NODES) if (collect > CONNCOUNT_GC_MAX_NODES)
@ -177,6 +180,7 @@ static int __nf_conncount_add(struct net *net,
nf_ct_put(found_ct); nf_ct_put(found_ct);
} }
add_new_node:
if (WARN_ON_ONCE(list->count > INT_MAX)) if (WARN_ON_ONCE(list->count > INT_MAX))
return -EOVERFLOW; return -EOVERFLOW;
@ -190,6 +194,7 @@ static int __nf_conncount_add(struct net *net,
conn->jiffies32 = (u32)jiffies; conn->jiffies32 = (u32)jiffies;
list_add_tail(&conn->node, &list->head); list_add_tail(&conn->node, &list->head);
list->count++; list->count++;
list->last_gc = (u32)jiffies;
return 0; return 0;
} }
@ -214,6 +219,7 @@ void nf_conncount_list_init(struct nf_conncount_list *list)
spin_lock_init(&list->list_lock); spin_lock_init(&list->list_lock);
INIT_LIST_HEAD(&list->head); INIT_LIST_HEAD(&list->head);
list->count = 0; list->count = 0;
list->last_gc = (u32)jiffies;
} }
EXPORT_SYMBOL_GPL(nf_conncount_list_init); EXPORT_SYMBOL_GPL(nf_conncount_list_init);
@ -227,6 +233,10 @@ bool nf_conncount_gc_list(struct net *net,
unsigned int collected = 0; unsigned int collected = 0;
bool ret = false; bool ret = false;
/* don't bother if we just did GC */
if (time_is_after_eq_jiffies((unsigned long)READ_ONCE(list->last_gc)))
return false;
/* don't bother if other cpu is already doing GC */ /* don't bother if other cpu is already doing GC */
if (!spin_trylock(&list->list_lock)) if (!spin_trylock(&list->list_lock))
return false; return false;
@ -258,6 +268,7 @@ bool nf_conncount_gc_list(struct net *net,
if (!list->count) if (!list->count)
ret = true; ret = true;
list->last_gc = (u32)jiffies;
spin_unlock(&list->list_lock); spin_unlock(&list->list_lock);
return ret; return ret;

View File

@ -1714,6 +1714,7 @@ static int ctnetlink_done_list(struct netlink_callback *cb)
return 0; return 0;
} }
#ifdef CONFIG_NF_CONNTRACK_EVENTS
static int ctnetlink_dump_one_entry(struct sk_buff *skb, static int ctnetlink_dump_one_entry(struct sk_buff *skb,
struct netlink_callback *cb, struct netlink_callback *cb,
struct nf_conn *ct, struct nf_conn *ct,
@ -1754,6 +1755,7 @@ static int ctnetlink_dump_one_entry(struct sk_buff *skb,
return res; return res;
} }
#endif
static int static int
ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb) ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)

View File

@ -485,7 +485,6 @@ static bool tcp_in_window(struct nf_conn *ct,
struct nf_tcp_net *tn = nf_tcp_pernet(net); struct nf_tcp_net *tn = nf_tcp_pernet(net);
struct ip_ct_tcp_state *sender = &state->seen[dir]; struct ip_ct_tcp_state *sender = &state->seen[dir];
struct ip_ct_tcp_state *receiver = &state->seen[!dir]; struct ip_ct_tcp_state *receiver = &state->seen[!dir];
const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
__u32 seq, ack, sack, end, win, swin; __u32 seq, ack, sack, end, win, swin;
u16 win_raw; u16 win_raw;
s32 receiver_offset; s32 receiver_offset;
@ -508,18 +507,6 @@ static bool tcp_in_window(struct nf_conn *ct,
ack -= receiver_offset; ack -= receiver_offset;
sack -= receiver_offset; sack -= receiver_offset;
pr_debug("tcp_in_window: START\n");
pr_debug("tcp_in_window: ");
nf_ct_dump_tuple(tuple);
pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
seq, ack, receiver_offset, sack, receiver_offset, win, end);
pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
sender->td_scale,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
if (sender->td_maxwin == 0) { if (sender->td_maxwin == 0) {
/* /*
* Initialize sender data. * Initialize sender data.
@ -597,27 +584,10 @@ static bool tcp_in_window(struct nf_conn *ct,
*/ */
seq = end = sender->td_end; seq = end = sender->td_end;
pr_debug("tcp_in_window: ");
nf_ct_dump_tuple(tuple);
pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n",
seq, ack, receiver_offset, sack, receiver_offset, win, end);
pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
sender->td_scale,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
/* Is the ending sequence in the receive window (if available)? */ /* Is the ending sequence in the receive window (if available)? */
in_recv_win = !receiver->td_maxwin || in_recv_win = !receiver->td_maxwin ||
after(end, sender->td_end - receiver->td_maxwin - 1); after(end, sender->td_end - receiver->td_maxwin - 1);
pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
before(seq, sender->td_maxend + 1),
(in_recv_win ? 1 : 0),
before(sack, receiver->td_end + 1),
after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1));
if (before(seq, sender->td_maxend + 1) && if (before(seq, sender->td_maxend + 1) &&
in_recv_win && in_recv_win &&
before(sack, receiver->td_end + 1) && before(sack, receiver->td_end + 1) &&
@ -698,11 +668,6 @@ static bool tcp_in_window(struct nf_conn *ct,
} }
} }
pr_debug("tcp_in_window: res=%u sender end=%u maxend=%u maxwin=%u "
"receiver end=%u maxend=%u maxwin=%u\n",
res, sender->td_end, sender->td_maxend, sender->td_maxwin,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin);
return res; return res;
} }
@ -772,8 +737,6 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
enum tcp_conntrack new_state; enum tcp_conntrack new_state;
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
const struct nf_tcp_net *tn = nf_tcp_pernet(net); const struct nf_tcp_net *tn = nf_tcp_pernet(net);
const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[0];
const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[1];
/* Don't need lock here: this conntrack not in circulation yet */ /* Don't need lock here: this conntrack not in circulation yet */
new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE]; new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE];
@ -826,14 +789,6 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
/* tcp_packet will set them */ /* tcp_packet will set them */
ct->proto.tcp.last_index = TCP_NONE_SET; ct->proto.tcp.last_index = TCP_NONE_SET;
pr_debug("%s: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
__func__,
sender->td_end, sender->td_maxend, sender->td_maxwin,
sender->td_scale,
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
receiver->td_scale);
return true; return true;
} }
@ -1032,10 +987,11 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
} }
/* Invalid packet */ /* Invalid packet */
pr_debug("nf_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
dir, get_conntrack_index(th), old_state);
spin_unlock_bh(&ct->lock); spin_unlock_bh(&ct->lock);
nf_ct_l4proto_log_invalid(skb, ct, state, "invalid state"); nf_ct_l4proto_log_invalid(skb, ct, state,
"packet (index %d) in dir %d invalid, state %s",
index, dir,
tcp_conntrack_names[old_state]);
return -NF_ACCEPT; return -NF_ACCEPT;
case TCP_CONNTRACK_TIME_WAIT: case TCP_CONNTRACK_TIME_WAIT:
/* RFC5961 compliance cause stack to send "challenge-ACK" /* RFC5961 compliance cause stack to send "challenge-ACK"