Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Browse files Browse the repository at this point in the history
Pablo Neira Ayuso says:

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

The following patchset contains Netfilter updates for net-next:

1) Wildcard support for the net,iface set from Kristian Evensen.

2) Offload support for matching on the input interface.

3) Simplify matching on vlan header fields.

4) Add nft_payload_rebuild_vlan_hdr() function to rebuild the vlan
   header from the vlan sk_buff metadata.

5) Pass extack to nft_flow_cls_offload_setup().

6) Add C-VLAN matching support.

7) Use time64_t in xt_time to fix y2038 overflow, from Arnd Bergmann.

8) Use time_t in nft_meta to fix y2038 overflow, also from Arnd.

9) Add flow_action_entry_next() helper function to flowtable offload
   infrastructure.

10) Add IPv6 support to the flowtable offload infrastructure.

11) Support for input interface matching from postrouting,
    from Phil Sutter.

12) Missing check for ndo callback in flowtable offload, from wenxu.

13) Remove conntrack parameter from flow_offload_fill_dir(), from wenxu.

14) Do not pass flow_rule object for rule removal, cookie is sufficient
    to achieve this.

15) Release flow_rule object in case of error from the offload commit
    path.

16) Undo offload ruleset updates if transaction fails.

17) Check for error when binding flowtable callbacks, from wenxu.

18) Always unbind flowtable callbacks when unregistering hooks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 19, 2019
2 parents 19b7e21 + ff4bf2f commit 99638e9
Show file tree
Hide file tree
Showing 18 changed files with 370 additions and 126 deletions.
9 changes: 6 additions & 3 deletions include/net/netfilter/nf_flow_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,12 @@ void nf_flow_table_offload_flush(struct nf_flowtable *flowtable);
int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
struct net_device *dev,
enum flow_block_command cmd);
int nf_flow_rule_route(struct net *net, const struct flow_offload *flow,
enum flow_offload_tuple_dir dir,
struct nf_flow_rule *flow_rule);
int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow,
enum flow_offload_tuple_dir dir,
struct nf_flow_rule *flow_rule);
int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow,
enum flow_offload_tuple_dir dir,
struct nf_flow_rule *flow_rule);

int nf_flow_table_offload_init(void);
void nf_flow_table_offload_exit(void);
Expand Down
1 change: 1 addition & 0 deletions include/net/netfilter/nf_tables_offload.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct nft_flow_key {
struct flow_dissector_key_ip ip;
struct flow_dissector_key_vlan vlan;
struct flow_dissector_key_eth_addrs eth_addrs;
struct flow_dissector_key_meta meta;
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */

struct nft_flow_match {
Expand Down
2 changes: 2 additions & 0 deletions include/uapi/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ enum ipset_cadt_flags {
IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD),
IPSET_FLAG_BIT_WITH_SKBINFO = 6,
IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO),
IPSET_FLAG_BIT_IFACE_WILDCARD = 7,
IPSET_FLAG_IFACE_WILDCARD = (1 << IPSET_FLAG_BIT_IFACE_WILDCARD),
IPSET_FLAG_CADT_MAX = 15,
};

Expand Down
4 changes: 2 additions & 2 deletions net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,15 +422,15 @@ int ip_mc_output(struct net *net, struct sock *sk, struct sk_buff *skb)

int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev;

IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len);

skb->dev = dev;
skb->protocol = htons(ETH_P_IP);

return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
net, sk, skb, NULL, dev,
net, sk, skb, indev, dev,
ip_finish_output,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/netfilter/nf_flow_table_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static struct nf_flowtable_type flowtable_ipv4 = {
.family = NFPROTO_IPV4,
.init = nf_flow_table_init,
.setup = nf_flow_table_offload_setup,
.action = nf_flow_rule_route,
.action = nf_flow_rule_route_ipv4,
.free = nf_flow_table_free,
.hook = nf_flow_offload_ip_hook,
.owner = THIS_MODULE,
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/xfrm4_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
net, sk, skb, NULL, skb_dst(skb)->dev,
net, sk, skb, skb->dev, skb_dst(skb)->dev,
__xfrm4_output,
!(IPCB(skb)->flags & IPSKB_REROUTED));
}
Expand Down
4 changes: 2 additions & 2 deletions net/ipv6/ip6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *s

int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_device *dev = skb_dst(skb)->dev;
struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev;
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));

skb->protocol = htons(ETH_P_IPV6);
Expand All @@ -173,7 +173,7 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
}

return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
net, sk, skb, NULL, dev,
net, sk, skb, indev, dev,
ip6_finish_output,
!(IP6CB(skb)->flags & IP6SKB_REROUTED));
}
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/netfilter/nf_flow_table_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ static struct nf_flowtable_type flowtable_ipv6 = {
.family = NFPROTO_IPV6,
.init = nf_flow_table_init,
.setup = nf_flow_table_offload_setup,
.action = nf_flow_rule_route,
.action = nf_flow_rule_route_ipv6,
.free = nf_flow_table_free,
.hook = nf_flow_offload_ipv6_hook,
.owner = THIS_MODULE,
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/xfrm6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
net, sk, skb, NULL, skb_dst(skb)->dev,
net, sk, skb, skb->dev, skb_dst(skb)->dev,
__xfrm6_output,
!(IP6CB(skb)->flags & IP6SKB_REROUTED));
}
23 changes: 18 additions & 5 deletions net/netfilter/ipset/ip_set_hash_netiface.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
/* 3 Counters support added */
/* 4 Comments support added */
/* 5 Forceadd support added */
#define IPSET_TYPE_REV_MAX 6 /* skbinfo support added */
/* 6 skbinfo support added */
#define IPSET_TYPE_REV_MAX 7 /* interface wildcard support added */

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
Expand Down Expand Up @@ -57,6 +58,7 @@ struct hash_netiface4_elem {
u8 cidr;
u8 nomatch;
u8 elem;
u8 wildcard;
char iface[IFNAMSIZ];
};

Expand All @@ -71,7 +73,9 @@ hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
ip1->cidr == ip2->cidr &&
(++*multi) &&
ip1->physdev == ip2->physdev &&
strcmp(ip1->iface, ip2->iface) == 0;
(ip1->wildcard ?
strncmp(ip1->iface, ip2->iface, strlen(ip1->iface)) == 0 :
strcmp(ip1->iface, ip2->iface) == 0);
}

static int
Expand Down Expand Up @@ -103,7 +107,8 @@ static bool
hash_netiface4_data_list(struct sk_buff *skb,
const struct hash_netiface4_elem *data)
{
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
u32 flags = (data->physdev ? IPSET_FLAG_PHYSDEV : 0) |
(data->wildcard ? IPSET_FLAG_IFACE_WILDCARD : 0);

if (data->nomatch)
flags |= IPSET_FLAG_NOMATCH;
Expand Down Expand Up @@ -229,6 +234,8 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
e.physdev = 1;
if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (IPSET_FLAG_NOMATCH << 16);
if (cadt_flags & IPSET_FLAG_IFACE_WILDCARD)
e.wildcard = 1;
}
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
e.ip = htonl(ip & ip_set_hostmask(e.cidr));
Expand Down Expand Up @@ -280,6 +287,7 @@ struct hash_netiface6_elem {
u8 cidr;
u8 nomatch;
u8 elem;
u8 wildcard;
char iface[IFNAMSIZ];
};

Expand All @@ -294,7 +302,9 @@ hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
ip1->cidr == ip2->cidr &&
(++*multi) &&
ip1->physdev == ip2->physdev &&
strcmp(ip1->iface, ip2->iface) == 0;
(ip1->wildcard ?
strncmp(ip1->iface, ip2->iface, strlen(ip1->iface)) == 0 :
strcmp(ip1->iface, ip2->iface) == 0);
}

static int
Expand Down Expand Up @@ -326,7 +336,8 @@ static bool
hash_netiface6_data_list(struct sk_buff *skb,
const struct hash_netiface6_elem *data)
{
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
u32 flags = (data->physdev ? IPSET_FLAG_PHYSDEV : 0) |
(data->wildcard ? IPSET_FLAG_IFACE_WILDCARD : 0);

if (data->nomatch)
flags |= IPSET_FLAG_NOMATCH;
Expand Down Expand Up @@ -440,6 +451,8 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
e.physdev = 1;
if (cadt_flags & IPSET_FLAG_NOMATCH)
flags |= (IPSET_FLAG_NOMATCH << 16);
if (cadt_flags & IPSET_FLAG_IFACE_WILDCARD)
e.wildcard = 1;
}

ret = adtfn(set, &e, &ext, &ext, flags);
Expand Down
8 changes: 4 additions & 4 deletions net/netfilter/nf_flow_table_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ static DEFINE_MUTEX(flowtable_lock);
static LIST_HEAD(flowtables);

static void
flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
flow_offload_fill_dir(struct flow_offload *flow,
enum flow_offload_tuple_dir dir)
{
struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
struct nf_conntrack_tuple *ctt = &flow->ct->tuplehash[dir].tuple;

ft->dir = dir;

Expand Down Expand Up @@ -57,8 +57,8 @@ struct flow_offload *flow_offload_alloc(struct nf_conn *ct)

flow->ct = ct;

flow_offload_fill_dir(flow, ct, FLOW_OFFLOAD_DIR_ORIGINAL);
flow_offload_fill_dir(flow, ct, FLOW_OFFLOAD_DIR_REPLY);
flow_offload_fill_dir(flow, FLOW_OFFLOAD_DIR_ORIGINAL);
flow_offload_fill_dir(flow, FLOW_OFFLOAD_DIR_REPLY);

if (ct->status & IPS_SRC_NAT)
flow->flags |= FLOW_OFFLOAD_SNAT;
Expand Down
25 changes: 24 additions & 1 deletion net/netfilter/nf_flow_table_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,34 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
return NF_ACCEPT;
}

static int nf_flow_rule_route_inet(struct net *net,
const struct flow_offload *flow,
enum flow_offload_tuple_dir dir,
struct nf_flow_rule *flow_rule)
{
const struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
int err;

switch (flow_tuple->l3proto) {
case NFPROTO_IPV4:
err = nf_flow_rule_route_ipv4(net, flow, dir, flow_rule);
break;
case NFPROTO_IPV6:
err = nf_flow_rule_route_ipv6(net, flow, dir, flow_rule);
break;
default:
err = -1;
break;
}

return err;
}

static struct nf_flowtable_type flowtable_inet = {
.family = NFPROTO_INET,
.init = nf_flow_table_init,
.setup = nf_flow_table_offload_setup,
.action = nf_flow_rule_route,
.action = nf_flow_rule_route_inet,
.free = nf_flow_table_free,
.hook = nf_flow_offload_inet_hook,
.owner = THIS_MODULE,
Expand Down
Loading

0 comments on commit 99638e9

Please sign in to comment.