Skip to content

Commit f1363e0

Browse files
ummakynesdavem330
authored andcommitted
netfilter: nf_flow_table: detach routing information from flow description
This patch adds the infrastructure to support for flow entry types. The initial type is NF_FLOW_OFFLOAD_ROUTE that stores the routing information into the flow entry to define a fastpath for the classic forwarding path. Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 62248df commit f1363e0

File tree

3 files changed

+80
-27
lines changed

3 files changed

+80
-27
lines changed

include/net/netfilter/nf_flow_table.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,16 @@ struct flow_offload_tuple_rhash {
7070
#define FLOW_OFFLOAD_DYING 0x4
7171
#define FLOW_OFFLOAD_TEARDOWN 0x8
7272

73+
enum flow_offload_type {
74+
NF_FLOW_OFFLOAD_UNSPEC = 0,
75+
NF_FLOW_OFFLOAD_ROUTE,
76+
};
77+
7378
struct flow_offload {
7479
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
7580
struct nf_conn *ct;
76-
u32 flags;
81+
u16 flags;
82+
u16 type;
7783
u32 timeout;
7884
struct rcu_head rcu_head;
7985
};
@@ -86,10 +92,12 @@ struct nf_flow_route {
8692
} tuple[FLOW_OFFLOAD_DIR_MAX];
8793
};
8894

89-
struct flow_offload *flow_offload_alloc(struct nf_conn *ct,
90-
struct nf_flow_route *route);
95+
struct flow_offload *flow_offload_alloc(struct nf_conn *ct);
9196
void flow_offload_free(struct flow_offload *flow);
9297

98+
int flow_offload_route_init(struct flow_offload *flow,
99+
const struct nf_flow_route *route);
100+
93101
int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
94102
struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table,
95103
struct flow_offload_tuple *tuple);

net/netfilter/nf_flow_table_core.c

Lines changed: 65 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,31 @@ static LIST_HEAD(flowtables);
1919

2020
static void
2121
flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
22-
struct nf_flow_route *route,
2322
enum flow_offload_tuple_dir dir)
2423
{
2524
struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
2625
struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
27-
struct dst_entry *other_dst = route->tuple[!dir].dst;
28-
struct dst_entry *dst = route->tuple[dir].dst;
2926

3027
ft->dir = dir;
3128

3229
switch (ctt->src.l3num) {
3330
case NFPROTO_IPV4:
3431
ft->src_v4 = ctt->src.u3.in;
3532
ft->dst_v4 = ctt->dst.u3.in;
36-
ft->mtu = ip_dst_mtu_maybe_forward(dst, true);
3733
break;
3834
case NFPROTO_IPV6:
3935
ft->src_v6 = ctt->src.u3.in6;
4036
ft->dst_v6 = ctt->dst.u3.in6;
41-
ft->mtu = ip6_dst_mtu_forward(dst);
4237
break;
4338
}
4439

4540
ft->l3proto = ctt->src.l3num;
4641
ft->l4proto = ctt->dst.protonum;
4742
ft->src_port = ctt->src.u.tcp.port;
4843
ft->dst_port = ctt->dst.u.tcp.port;
49-
50-
ft->iifidx = other_dst->dev->ifindex;
51-
ft->dst_cache = dst;
5244
}
5345

54-
struct flow_offload *
55-
flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route)
46+
struct flow_offload *flow_offload_alloc(struct nf_conn *ct)
5647
{
5748
struct flow_offload *flow;
5849

@@ -64,16 +55,10 @@ flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route)
6455
if (!flow)
6556
goto err_ct_refcnt;
6657

67-
if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst))
68-
goto err_dst_cache_original;
69-
70-
if (!dst_hold_safe(route->tuple[FLOW_OFFLOAD_DIR_REPLY].dst))
71-
goto err_dst_cache_reply;
72-
7358
flow->ct = ct;
7459

75-
flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_ORIGINAL);
76-
flow_offload_fill_dir(flow, ct, route, FLOW_OFFLOAD_DIR_REPLY);
60+
flow_offload_fill_dir(flow, ct, FLOW_OFFLOAD_DIR_ORIGINAL);
61+
flow_offload_fill_dir(flow, ct, FLOW_OFFLOAD_DIR_REPLY);
7762

7863
if (ct->status & IPS_SRC_NAT)
7964
flow->flags |= FLOW_OFFLOAD_SNAT;
@@ -82,17 +67,63 @@ flow_offload_alloc(struct nf_conn *ct, struct nf_flow_route *route)
8267

8368
return flow;
8469

85-
err_dst_cache_reply:
86-
dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst);
87-
err_dst_cache_original:
88-
kfree(flow);
8970
err_ct_refcnt:
9071
nf_ct_put(ct);
9172

9273
return NULL;
9374
}
9475
EXPORT_SYMBOL_GPL(flow_offload_alloc);
9576

77+
static int flow_offload_fill_route(struct flow_offload *flow,
78+
const struct nf_flow_route *route,
79+
enum flow_offload_tuple_dir dir)
80+
{
81+
struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
82+
struct dst_entry *other_dst = route->tuple[!dir].dst;
83+
struct dst_entry *dst = route->tuple[dir].dst;
84+
85+
if (!dst_hold_safe(route->tuple[dir].dst))
86+
return -1;
87+
88+
switch (flow_tuple->l3proto) {
89+
case NFPROTO_IPV4:
90+
flow_tuple->mtu = ip_dst_mtu_maybe_forward(dst, true);
91+
break;
92+
case NFPROTO_IPV6:
93+
flow_tuple->mtu = ip6_dst_mtu_forward(dst);
94+
break;
95+
}
96+
97+
flow_tuple->iifidx = other_dst->dev->ifindex;
98+
flow_tuple->dst_cache = dst;
99+
100+
return 0;
101+
}
102+
103+
int flow_offload_route_init(struct flow_offload *flow,
104+
const struct nf_flow_route *route)
105+
{
106+
int err;
107+
108+
err = flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL);
109+
if (err < 0)
110+
return err;
111+
112+
err = flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY);
113+
if (err < 0)
114+
goto err_route_reply;
115+
116+
flow->type = NF_FLOW_OFFLOAD_ROUTE;
117+
118+
return 0;
119+
120+
err_route_reply:
121+
dst_release(route->tuple[FLOW_OFFLOAD_DIR_ORIGINAL].dst);
122+
123+
return err;
124+
}
125+
EXPORT_SYMBOL_GPL(flow_offload_route_init);
126+
96127
static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
97128
{
98129
tcp->state = TCP_CONNTRACK_ESTABLISHED;
@@ -141,10 +172,21 @@ static void flow_offload_fixup_ct(struct nf_conn *ct)
141172
flow_offload_fixup_ct_timeout(ct);
142173
}
143174

144-
void flow_offload_free(struct flow_offload *flow)
175+
static void flow_offload_route_release(struct flow_offload *flow)
145176
{
146177
dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_cache);
147178
dst_release(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_cache);
179+
}
180+
181+
void flow_offload_free(struct flow_offload *flow)
182+
{
183+
switch (flow->type) {
184+
case NF_FLOW_OFFLOAD_ROUTE:
185+
flow_offload_route_release(flow);
186+
break;
187+
default:
188+
break;
189+
}
148190
if (flow->flags & FLOW_OFFLOAD_DYING)
149191
nf_ct_delete(flow->ct, 0, 0);
150192
nf_ct_put(flow->ct);

net/netfilter/nft_flow_offload.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,13 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
115115
if (nft_flow_route(pkt, ct, &route, dir) < 0)
116116
goto err_flow_route;
117117

118-
flow = flow_offload_alloc(ct, &route);
118+
flow = flow_offload_alloc(ct);
119119
if (!flow)
120120
goto err_flow_alloc;
121121

122+
if (flow_offload_route_init(flow, &route) < 0)
123+
goto err_flow_add;
124+
122125
if (tcph) {
123126
ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
124127
ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;

0 commit comments

Comments
 (0)