mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
datapath: Add support for IPv6 tunnels.
Mostly backports upstream commit along with other pieces to make IPv6 tunneling work. commit 6b26ba3a7d952e611dcde1f3f77ce63bcc70540a Author: Jiri Benc <jbenc@redhat.com> openvswitch: netlink attributes for IPv6 tunneling Add netlink attributes for IPv6 tunnel addresses. This enables IPv6 support for tunnels. Signed-off-by: Jiri Benc <jbenc@redhat.com> Acked-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Jesse Gross <jesse@kernel.org>
This commit is contained in:
parent
f2252c6105
commit
8a2d4905a0
3
FAQ.md
3
FAQ.md
@ -199,6 +199,9 @@ Tunnel - STT | NO | YES | NO | YES |
|
|||||||
Tunnel - GRE | 3.11 | YES | YES | YES |
|
Tunnel - GRE | 3.11 | YES | YES | YES |
|
||||||
Tunnel - VXLAN | 3.12 | YES | YES | YES |
|
Tunnel - VXLAN | 3.12 | YES | YES | YES |
|
||||||
Tunnel - Geneve | 3.18 | YES | YES | YES |
|
Tunnel - Geneve | 3.18 | YES | YES | YES |
|
||||||
|
Tunnel - GRE-IPv6 | NO | NO | YES | NO |
|
||||||
|
Tunnel - VXLAN-IPv6 | 4.3 | YES | YES | NO |
|
||||||
|
Tunnel - Geneve-IPv6 | 4.4 | YES | YES | NO |
|
||||||
QoS - Policing | YES | YES | NO | NO |
|
QoS - Policing | YES | YES | NO | NO |
|
||||||
QoS - Shaping | YES | YES | NO | NO |
|
QoS - Shaping | YES | YES | NO | NO |
|
||||||
sFlow | YES | YES | YES | NO |
|
sFlow | YES | YES | YES | NO |
|
||||||
|
2
NEWS
2
NEWS
@ -75,7 +75,7 @@ Post-v2.5.0
|
|||||||
- Tunnels:
|
- Tunnels:
|
||||||
* Flow based tunnel match and action can be used for IPv6 address using
|
* Flow based tunnel match and action can be used for IPv6 address using
|
||||||
tun_ipv6_src, tun_ipv6_dst fields.
|
tun_ipv6_src, tun_ipv6_dst fields.
|
||||||
* Added support for IPv6 tunnels to native tunneling.
|
* Added support for IPv6 tunnels, for details checkout FAQ.
|
||||||
- A wrapper script, 'ovs-tcpdump', to easily port-mirror an OVS port and
|
- A wrapper script, 'ovs-tcpdump', to easily port-mirror an OVS port and
|
||||||
watch with tcpdump
|
watch with tcpdump
|
||||||
- Introduce --no-self-confinement flag that allows daemons to work with
|
- Introduce --no-self-confinement flag that allows daemons to work with
|
||||||
|
@ -689,9 +689,7 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
|
|||||||
{
|
{
|
||||||
/* Extract metadata from packet. */
|
/* Extract metadata from packet. */
|
||||||
if (tun_info) {
|
if (tun_info) {
|
||||||
if (ip_tunnel_info_af(tun_info) != AF_INET)
|
key->tun_proto = ip_tunnel_info_af(tun_info);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key));
|
memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key));
|
||||||
BUILD_BUG_ON(((1 << (sizeof(tun_info->options_len) * 8)) - 1) >
|
BUILD_BUG_ON(((1 << (sizeof(tun_info->options_len) * 8)) - 1) >
|
||||||
sizeof(key->tun_opts));
|
sizeof(key->tun_opts));
|
||||||
@ -703,7 +701,8 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
|
|||||||
} else {
|
} else {
|
||||||
key->tun_opts_len = 0;
|
key->tun_opts_len = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
key->tun_proto = 0;
|
||||||
key->tun_opts_len = 0;
|
key->tun_opts_len = 0;
|
||||||
memset(&key->tun_key, 0, sizeof(key->tun_key));
|
memset(&key->tun_key, 0, sizeof(key->tun_key));
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ struct sw_flow_key {
|
|||||||
u32 skb_mark; /* SKB mark. */
|
u32 skb_mark; /* SKB mark. */
|
||||||
u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
|
u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
|
||||||
} __packed phy; /* Safe when right after 'tun_key'. */
|
} __packed phy; /* Safe when right after 'tun_key'. */
|
||||||
|
u8 tun_proto; /* Protocol of encapsulating tunnel. */
|
||||||
u32 ovs_flow_hash; /* Datapath computed hash value. */
|
u32 ovs_flow_hash; /* Datapath computed hash value. */
|
||||||
u32 recirc_id; /* Recirculation ID. */
|
u32 recirc_id; /* Recirculation ID. */
|
||||||
struct {
|
struct {
|
||||||
|
@ -263,9 +263,9 @@ size_t ovs_tun_key_attr_size(void)
|
|||||||
/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
|
/* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
|
||||||
* updating this function.
|
* updating this function.
|
||||||
*/
|
*/
|
||||||
return nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
|
return nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
|
||||||
+ nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
|
+ nla_total_size(16) /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */
|
||||||
+ nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
|
+ nla_total_size(16) /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */
|
||||||
+ nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
|
+ nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
|
||||||
+ nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
|
+ nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
|
||||||
+ nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
|
+ nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
|
||||||
@ -325,6 +325,8 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
|
|||||||
[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_VARIABLE },
|
[OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_VARIABLE },
|
||||||
[OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = OVS_ATTR_NESTED,
|
[OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = OVS_ATTR_NESTED,
|
||||||
.next = ovs_vxlan_ext_key_lens },
|
.next = ovs_vxlan_ext_key_lens },
|
||||||
|
[OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
|
||||||
|
[OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
|
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
|
||||||
@ -544,15 +546,15 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipv4_tun_from_nlattr(const struct nlattr *attr,
|
static int ip_tun_from_nlattr(const struct nlattr *attr,
|
||||||
struct sw_flow_match *match, bool is_mask,
|
struct sw_flow_match *match, bool is_mask,
|
||||||
bool log)
|
bool log)
|
||||||
{
|
{
|
||||||
struct nlattr *a;
|
bool ttl = false, ipv4 = false, ipv6 = false;
|
||||||
int rem;
|
|
||||||
bool ttl = false;
|
|
||||||
__be16 tun_flags = 0;
|
__be16 tun_flags = 0;
|
||||||
int opts_type = 0;
|
int opts_type = 0;
|
||||||
|
struct nlattr *a;
|
||||||
|
int rem;
|
||||||
|
|
||||||
nla_for_each_nested(a, attr, rem) {
|
nla_for_each_nested(a, attr, rem) {
|
||||||
int type = nla_type(a);
|
int type = nla_type(a);
|
||||||
@ -580,10 +582,22 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
|
|||||||
case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
|
case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
|
||||||
SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src,
|
SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src,
|
||||||
nla_get_in_addr(a), is_mask);
|
nla_get_in_addr(a), is_mask);
|
||||||
|
ipv4 = true;
|
||||||
break;
|
break;
|
||||||
case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
|
case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
|
||||||
SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst,
|
SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst,
|
||||||
nla_get_in_addr(a), is_mask);
|
nla_get_in_addr(a), is_mask);
|
||||||
|
ipv4 = true;
|
||||||
|
break;
|
||||||
|
case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
|
||||||
|
SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
|
||||||
|
nla_get_in6_addr(a), is_mask);
|
||||||
|
ipv6 = true;
|
||||||
|
break;
|
||||||
|
case OVS_TUNNEL_KEY_ATTR_IPV6_DST:
|
||||||
|
SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
|
||||||
|
nla_get_in6_addr(a), is_mask);
|
||||||
|
ipv6 = true;
|
||||||
break;
|
break;
|
||||||
case OVS_TUNNEL_KEY_ATTR_TOS:
|
case OVS_TUNNEL_KEY_ATTR_TOS:
|
||||||
SW_FLOW_KEY_PUT(match, tun_key.tos,
|
SW_FLOW_KEY_PUT(match, tun_key.tos,
|
||||||
@ -638,28 +652,46 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
|
|||||||
opts_type = type;
|
opts_type = type;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
OVS_NLERR(log, "Unknown IPv4 tunnel attribute %d",
|
OVS_NLERR(log, "Unknown IP tunnel attribute %d",
|
||||||
type);
|
type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
|
SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
|
||||||
|
if (is_mask)
|
||||||
|
SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true);
|
||||||
|
else
|
||||||
|
SW_FLOW_KEY_PUT(match, tun_proto, ipv6 ? AF_INET6 : AF_INET,
|
||||||
|
false);
|
||||||
|
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
OVS_NLERR(log, "IPv4 tunnel attribute has %d unknown bytes.",
|
OVS_NLERR(log, "IP tunnel attribute has %d unknown bytes.",
|
||||||
rem);
|
rem);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ipv4 && ipv6) {
|
||||||
|
OVS_NLERR(log, "Mixed IPv4 and IPv6 tunnel attributes");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_mask) {
|
if (!is_mask) {
|
||||||
if (!match->key->tun_key.u.ipv4.dst) {
|
if (!ipv4 && !ipv6) {
|
||||||
|
OVS_NLERR(log, "IP tunnel dst address not specified");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (ipv4 && !match->key->tun_key.u.ipv4.dst) {
|
||||||
OVS_NLERR(log, "IPv4 tunnel dst address is zero");
|
OVS_NLERR(log, "IPv4 tunnel dst address is zero");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) {
|
||||||
|
OVS_NLERR(log, "IPv6 tunnel dst address is zero");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ttl) {
|
if (!ttl) {
|
||||||
OVS_NLERR(log, "IPv4 tunnel TTL not specified.");
|
OVS_NLERR(log, "IP tunnel TTL not specified.");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,21 +716,36 @@ static int vxlan_opt_to_nlattr(struct sk_buff *skb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
|
static int __ip_tun_to_nlattr(struct sk_buff *skb,
|
||||||
const struct ip_tunnel_key *output,
|
const struct ip_tunnel_key *output,
|
||||||
const void *tun_opts, int swkey_tun_opts_len)
|
const void *tun_opts, int swkey_tun_opts_len,
|
||||||
|
unsigned short tun_proto)
|
||||||
{
|
{
|
||||||
if (output->tun_flags & TUNNEL_KEY &&
|
if (output->tun_flags & TUNNEL_KEY &&
|
||||||
nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
|
nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
if (output->u.ipv4.src &&
|
switch (tun_proto) {
|
||||||
nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
|
case AF_INET:
|
||||||
output->u.ipv4.src))
|
if (output->u.ipv4.src &&
|
||||||
return -EMSGSIZE;
|
nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
|
||||||
if (output->u.ipv4.dst &&
|
output->u.ipv4.src))
|
||||||
nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
|
return -EMSGSIZE;
|
||||||
output->u.ipv4.dst))
|
if (output->u.ipv4.dst &&
|
||||||
return -EMSGSIZE;
|
nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
|
||||||
|
output->u.ipv4.dst))
|
||||||
|
return -EMSGSIZE;
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
if (!ipv6_addr_any(&output->u.ipv6.src) &&
|
||||||
|
nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,
|
||||||
|
&output->u.ipv6.src))
|
||||||
|
return -EMSGSIZE;
|
||||||
|
if (!ipv6_addr_any(&output->u.ipv6.dst) &&
|
||||||
|
nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_DST,
|
||||||
|
&output->u.ipv6.dst))
|
||||||
|
return -EMSGSIZE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (output->tos &&
|
if (output->tos &&
|
||||||
nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos))
|
nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos))
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
@ -732,9 +779,10 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipv4_tun_to_nlattr(struct sk_buff *skb,
|
static int ip_tun_to_nlattr(struct sk_buff *skb,
|
||||||
const struct ip_tunnel_key *output,
|
const struct ip_tunnel_key *output,
|
||||||
const void *tun_opts, int swkey_tun_opts_len)
|
const void *tun_opts, int swkey_tun_opts_len,
|
||||||
|
unsigned short tun_proto)
|
||||||
{
|
{
|
||||||
struct nlattr *nla;
|
struct nlattr *nla;
|
||||||
int err;
|
int err;
|
||||||
@ -743,7 +791,8 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
|
|||||||
if (!nla)
|
if (!nla)
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
|
||||||
err = __ipv4_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len);
|
err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len,
|
||||||
|
tun_proto);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
@ -754,9 +803,10 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
|
|||||||
int ovs_nla_put_tunnel_info(struct sk_buff *skb,
|
int ovs_nla_put_tunnel_info(struct sk_buff *skb,
|
||||||
struct ip_tunnel_info *tun_info)
|
struct ip_tunnel_info *tun_info)
|
||||||
{
|
{
|
||||||
return __ipv4_tun_to_nlattr(skb, &tun_info->key,
|
return __ip_tun_to_nlattr(skb, &tun_info->key,
|
||||||
ip_tunnel_info_opts(tun_info),
|
ip_tunnel_info_opts(tun_info),
|
||||||
tun_info->options_len);
|
tun_info->options_len,
|
||||||
|
ip_tunnel_info_af(tun_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
|
static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
|
||||||
@ -807,7 +857,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
|
|||||||
*attrs &= ~(1ULL << OVS_KEY_ATTR_SKB_MARK);
|
*attrs &= ~(1ULL << OVS_KEY_ATTR_SKB_MARK);
|
||||||
}
|
}
|
||||||
if (*attrs & (1ULL << OVS_KEY_ATTR_TUNNEL)) {
|
if (*attrs & (1ULL << OVS_KEY_ATTR_TUNNEL)) {
|
||||||
if (ipv4_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
|
if (ip_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
|
||||||
is_mask, log) < 0)
|
is_mask, log) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
*attrs &= ~(1ULL << OVS_KEY_ATTR_TUNNEL);
|
*attrs &= ~(1ULL << OVS_KEY_ATTR_TUNNEL);
|
||||||
@ -944,8 +994,7 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
|
if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
|
||||||
OVS_NLERR(log,
|
OVS_NLERR(log, "IPv6 flow label %x is out of range (max=%x).\n",
|
||||||
"Invalid IPv6 flow label value (value=%x, max=%x).",
|
|
||||||
ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
|
ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1379,14 +1428,14 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
|
|||||||
if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
|
if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
|
|
||||||
if ((swkey->tun_key.u.ipv4.dst || is_mask)) {
|
if ((swkey->tun_proto || is_mask)) {
|
||||||
const void *opts = NULL;
|
const void *opts = NULL;
|
||||||
|
|
||||||
if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT)
|
if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT)
|
||||||
opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len);
|
opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len);
|
||||||
|
|
||||||
if (ipv4_tun_to_nlattr(skb, &output->tun_key, opts,
|
if (ip_tun_to_nlattr(skb, &output->tun_key, opts,
|
||||||
swkey->tun_opts_len))
|
swkey->tun_opts_len, swkey->tun_proto))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1684,8 +1733,7 @@ static void __ovs_nla_free_flow_actions(struct rcu_head *head)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Schedules 'sf_acts' to be freed after the next RCU grace period.
|
/* Schedules 'sf_acts' to be freed after the next RCU grace period.
|
||||||
* The caller must hold rcu_read_lock for this to be sensible.
|
* The caller must hold rcu_read_lock for this to be sensible. */
|
||||||
*/
|
|
||||||
void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *sf_acts)
|
void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *sf_acts)
|
||||||
{
|
{
|
||||||
call_rcu(&sf_acts->rcu, __ovs_nla_free_flow_actions);
|
call_rcu(&sf_acts->rcu, __ovs_nla_free_flow_actions);
|
||||||
@ -1892,7 +1940,7 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
|
|||||||
int err = 0, start, opts_type;
|
int err = 0, start, opts_type;
|
||||||
|
|
||||||
ovs_match_init(&match, &key, NULL);
|
ovs_match_init(&match, &key, NULL);
|
||||||
opts_type = ipv4_tun_from_nlattr(nla_data(attr), &match, false, log);
|
opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
|
||||||
if (opts_type < 0)
|
if (opts_type < 0)
|
||||||
return opts_type;
|
return opts_type;
|
||||||
|
|
||||||
@ -1928,6 +1976,8 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
|
|||||||
|
|
||||||
tun_info = &tun_dst->u.tun_info;
|
tun_info = &tun_dst->u.tun_info;
|
||||||
tun_info->mode = IP_TUNNEL_INFO_TX;
|
tun_info->mode = IP_TUNNEL_INFO_TX;
|
||||||
|
if (key.tun_proto == AF_INET6)
|
||||||
|
tun_info->mode |= IP_TUNNEL_INFO_IPV6;
|
||||||
tun_info->key = key.tun_key;
|
tun_info->key = key.tun_key;
|
||||||
|
|
||||||
/* We need to store the options in the action itself since
|
/* We need to store the options in the action itself since
|
||||||
|
Loading…
x
Reference in New Issue
Block a user