Skip to content

Commit 34ae932

Browse files
tgrafdavem330
authored andcommitted
openvswitch: Make tunnel set action attach a metadata dst
Utilize the new metadata dst to attach encapsulation instructions to the skb. The existing egress_tun_info via the OVS_CB() is left in place until all tunnel vports have been converted to the new method. Signed-off-by: Thomas Graf <[email protected]> Signed-off-by: Pravin B Shelar <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0dfbdf4 commit 34ae932

File tree

6 files changed

+79
-13
lines changed

6 files changed

+79
-13
lines changed

net/openvswitch/actions.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,15 @@ static int execute_set_action(struct sk_buff *skb,
733733
{
734734
/* Only tunnel set execution is supported without a mask. */
735735
if (nla_type(a) == OVS_KEY_ATTR_TUNNEL_INFO) {
736-
OVS_CB(skb)->egress_tun_info = nla_data(a);
736+
struct ovs_tunnel_info *tun = nla_data(a);
737+
738+
skb_dst_drop(skb);
739+
dst_hold((struct dst_entry *)tun->tun_dst);
740+
skb_dst_set(skb, (struct dst_entry *)tun->tun_dst);
741+
742+
/* FIXME: Remove when all vports have been converted */
743+
OVS_CB(skb)->egress_tun_info = &tun->tun_dst->u.tun_info;
744+
737745
return 0;
738746
}
739747

net/openvswitch/datapath.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
10181018
}
10191019
ovs_unlock();
10201020

1021-
ovs_nla_free_flow_actions(old_acts);
1021+
ovs_nla_free_flow_actions_rcu(old_acts);
10221022
ovs_flow_free(new_flow, false);
10231023
}
10241024

@@ -1030,7 +1030,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
10301030
ovs_unlock();
10311031
kfree_skb(reply);
10321032
err_kfree_acts:
1033-
kfree(acts);
1033+
ovs_nla_free_flow_actions(acts);
10341034
err_kfree_flow:
10351035
ovs_flow_free(new_flow, false);
10361036
error:
@@ -1157,15 +1157,15 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
11571157
if (reply)
11581158
ovs_notify(&dp_flow_genl_family, reply, info);
11591159
if (old_acts)
1160-
ovs_nla_free_flow_actions(old_acts);
1160+
ovs_nla_free_flow_actions_rcu(old_acts);
11611161

11621162
return 0;
11631163

11641164
err_unlock_ovs:
11651165
ovs_unlock();
11661166
kfree_skb(reply);
11671167
err_kfree_acts:
1168-
kfree(acts);
1168+
ovs_nla_free_flow_actions(acts);
11691169
error:
11701170
return error;
11711171
}

net/openvswitch/flow.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <linux/flex_array.h>
3434
#include <net/inet_ecn.h>
3535
#include <net/ip_tunnels.h>
36+
#include <net/dst_metadata.h>
3637

3738
struct sk_buff;
3839

@@ -45,6 +46,10 @@ struct sk_buff;
4546
#define TUN_METADATA_OPTS(flow_key, opt_len) \
4647
((void *)((flow_key)->tun_opts + TUN_METADATA_OFFSET(opt_len)))
4748

49+
struct ovs_tunnel_info {
50+
struct metadata_dst *tun_dst;
51+
};
52+
4853
#define OVS_SW_FLOW_KEY_METADATA_SIZE \
4954
(offsetof(struct sw_flow_key, recirc_id) + \
5055
FIELD_SIZEOF(struct sw_flow_key, recirc_id))

net/openvswitch/flow_netlink.c

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,11 +1548,48 @@ static struct sw_flow_actions *nla_alloc_flow_actions(int size, bool log)
15481548
return sfa;
15491549
}
15501550

1551+
static void ovs_nla_free_set_action(const struct nlattr *a)
1552+
{
1553+
const struct nlattr *ovs_key = nla_data(a);
1554+
struct ovs_tunnel_info *ovs_tun;
1555+
1556+
switch (nla_type(ovs_key)) {
1557+
case OVS_KEY_ATTR_TUNNEL_INFO:
1558+
ovs_tun = nla_data(ovs_key);
1559+
dst_release((struct dst_entry *)ovs_tun->tun_dst);
1560+
break;
1561+
}
1562+
}
1563+
1564+
void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
1565+
{
1566+
const struct nlattr *a;
1567+
int rem;
1568+
1569+
if (!sf_acts)
1570+
return;
1571+
1572+
nla_for_each_attr(a, sf_acts->actions, sf_acts->actions_len, rem) {
1573+
switch (nla_type(a)) {
1574+
case OVS_ACTION_ATTR_SET:
1575+
ovs_nla_free_set_action(a);
1576+
break;
1577+
}
1578+
}
1579+
1580+
kfree(sf_acts);
1581+
}
1582+
1583+
static void __ovs_nla_free_flow_actions(struct rcu_head *head)
1584+
{
1585+
ovs_nla_free_flow_actions(container_of(head, struct sw_flow_actions, rcu));
1586+
}
1587+
15511588
/* Schedules 'sf_acts' to be freed after the next RCU grace period.
15521589
* The caller must hold rcu_read_lock for this to be sensible. */
1553-
void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts)
1590+
void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *sf_acts)
15541591
{
1555-
kfree_rcu(sf_acts, rcu);
1592+
call_rcu(&sf_acts->rcu, __ovs_nla_free_flow_actions);
15561593
}
15571594

15581595
static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
@@ -1746,7 +1783,9 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
17461783
{
17471784
struct sw_flow_match match;
17481785
struct sw_flow_key key;
1786+
struct metadata_dst *tun_dst;
17491787
struct ip_tunnel_info *tun_info;
1788+
struct ovs_tunnel_info *ovs_tun;
17501789
struct nlattr *a;
17511790
int err = 0, start, opts_type;
17521791

@@ -1771,12 +1810,22 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
17711810
if (start < 0)
17721811
return start;
17731812

1813+
tun_dst = metadata_dst_alloc(key.tun_opts_len, GFP_KERNEL);
1814+
if (!tun_dst)
1815+
return -ENOMEM;
1816+
17741817
a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
1775-
sizeof(*tun_info) + key.tun_opts_len, log);
1776-
if (IS_ERR(a))
1818+
sizeof(*ovs_tun), log);
1819+
if (IS_ERR(a)) {
1820+
dst_release((struct dst_entry *)tun_dst);
17771821
return PTR_ERR(a);
1822+
}
1823+
1824+
ovs_tun = nla_data(a);
1825+
ovs_tun->tun_dst = tun_dst;
17781826

1779-
tun_info = nla_data(a);
1827+
tun_info = &tun_dst->u.tun_info;
1828+
tun_info->mode = IP_TUNNEL_INFO_TX;
17801829
tun_info->key = key.tun_key;
17811830
tun_info->options_len = key.tun_opts_len;
17821831

@@ -2177,7 +2226,7 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
21772226
err = __ovs_nla_copy_actions(attr, key, 0, sfa, key->eth.type,
21782227
key->eth.tci, log);
21792228
if (err)
2180-
kfree(*sfa);
2229+
ovs_nla_free_flow_actions(*sfa);
21812230

21822231
return err;
21832232
}
@@ -2227,7 +2276,8 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
22272276

22282277
switch (key_type) {
22292278
case OVS_KEY_ATTR_TUNNEL_INFO: {
2230-
struct ip_tunnel_info *tun_info = nla_data(ovs_key);
2279+
struct ovs_tunnel_info *ovs_tun = nla_data(ovs_key);
2280+
struct ip_tunnel_info *tun_info = &ovs_tun->tun_dst->u.tun_info;
22312281

22322282
start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
22332283
if (!start)

net/openvswitch/flow_netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ int ovs_nla_put_actions(const struct nlattr *attr,
6969
int len, struct sk_buff *skb);
7070

7171
void ovs_nla_free_flow_actions(struct sw_flow_actions *);
72+
void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *);
7273

7374
#endif /* flow_netlink.h */

net/openvswitch/flow_table.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "flow.h"
2020
#include "datapath.h"
21+
#include "flow_netlink.h"
2122
#include <linux/uaccess.h>
2223
#include <linux/netdevice.h>
2324
#include <linux/etherdevice.h>
@@ -143,7 +144,8 @@ static void flow_free(struct sw_flow *flow)
143144

144145
if (ovs_identifier_is_key(&flow->id))
145146
kfree(flow->id.unmasked_key);
146-
kfree((struct sw_flow_actions __force *)flow->sf_acts);
147+
if (flow->sf_acts)
148+
ovs_nla_free_flow_actions((struct sw_flow_actions __force *)flow->sf_acts);
147149
for_each_node(node)
148150
if (flow->stats[node])
149151
kmem_cache_free(flow_stats_cache,

0 commit comments

Comments
 (0)