#include <net/net_namespace.h>
#include <net/netns/generic.h>
-#include "checksum.h"
#include "datapath.h"
#include "flow.h"
#include "vlan.h"
-#include "tunnel.h"
#include "vport-internal_dev.h"
#include "vport-netdev.h"
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \
- LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)
-#error Kernels before 2.6.18 or after 3.8 are not supported by this version of Open vSwitch.
-#endif
-
#define REHASH_FLOW_INTERVAL (10 * 60 * HZ)
static void rehash_flow_table(struct work_struct *work);
static DECLARE_DELAYED_WORK(rehash_flow_wq, rehash_flow_table);
.name = OVS_PACKET_FAMILY,
.version = OVS_PACKET_VERSION,
.maxattr = OVS_PACKET_ATTR_MAX,
- SET_NETNSOK
+ .netnsok = true,
+ SET_PARALLEL_OPS
};
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
goto err;
}
- forward_ip_summed(skb, true);
-
if (!skb_is_gso(skb))
err = queue_userspace_packet(ovs_dp_get_net(dp), dp_ifindex, skb, upcall_info);
else
nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
return -ENOMEM;
-
- err = vlan_deaccel_tag(nskb);
- if (err)
- return err;
+
+ nskb = __vlan_put_tag(nskb, nskb->vlan_proto, vlan_tx_tag_get(nskb));
+ if (!nskb)
+ return -ENOMEM;
+
+ vlan_set_tci(nskb, 0);
skb = nskb;
}
int err, start;
ovs_match_init(&match, &key, NULL);
- err = ipv4_tun_from_nlattr(nla_data(attr), &match, false);
+ err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &match, false);
if (err)
return err;
int err;
case OVS_KEY_ATTR_PRIORITY:
- case OVS_KEY_ATTR_ETHERNET:
- break;
-
case OVS_KEY_ATTR_SKB_MARK:
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) && !defined(CONFIG_NETFILTER)
- if (nla_get_u32(ovs_key) != 0)
- return -EINVAL;
-#endif
+ case OVS_KEY_ATTR_ETHERNET:
break;
case OVS_KEY_ATTR_TUNNEL:
return validate_tp_port(flow_key);
+ case OVS_KEY_ATTR_SCTP:
+ if (flow_key->ip.proto != IPPROTO_SCTP)
+ return -EINVAL;
+
+ return validate_tp_port(flow_key);
+
default:
return -EINVAL;
}
OVS_CB(packet)->flow = flow;
OVS_CB(packet)->pkt_key = &flow->key;
packet->priority = flow->key.phy.priority;
- skb_set_mark(packet, flow->key.phy.skb_mark);
+ packet->mark = flow->key.phy.skb_mark;
rcu_read_lock();
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
}
static const struct nla_policy packet_policy[OVS_PACKET_ATTR_MAX + 1] = {
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
[OVS_PACKET_ATTR_PACKET] = { .len = ETH_HLEN },
-#else
- [OVS_PACKET_ATTR_PACKET] = { .minlen = ETH_HLEN },
-#endif
[OVS_PACKET_ATTR_KEY] = { .type = NLA_NESTED },
[OVS_PACKET_ATTR_ACTIONS] = { .type = NLA_NESTED },
};
.name = OVS_FLOW_FAMILY,
.version = OVS_FLOW_VERSION,
.maxattr = OVS_FLOW_ATTR_MAX,
- SET_NETNSOK
+ .netnsok = true,
+ SET_PARALLEL_OPS
};
static struct genl_multicast_group ovs_dp_flow_multicast_group = {
if (!start)
return -EMSGSIZE;
- err = ipv4_tun_to_nlattr(skb,
- nla_data(ovs_key), nla_data(ovs_key));
+ err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key),
+ nla_data(ovs_key));
if (err)
return err;
nla_nest_end(skb, start);
u32 seq, u32 flags, u8 cmd)
{
const int skb_orig_len = skb->len;
- struct sw_flow_mask *mask;
struct nlattr *start;
struct ovs_flow_stats stats;
struct ovs_header *ovs_header;
if (!nla)
goto nla_put_failure;
- mask = rcu_dereference_check(flow->mask, lockdep_ovsl_is_held());
- err = ovs_flow_to_nlattrs(&flow->key, &mask->key, skb);
+ err = ovs_flow_to_nlattrs(&flow->key, &flow->mask->key, skb);
if (err)
goto error;
}
ovs_sw_flow_mask_add_ref(mask_p);
- rcu_assign_pointer(flow->mask, mask_p);
+ flow->mask = mask_p;
rcu_assign_pointer(flow->sf_acts, acts);
/* Put flow in bucket. */
if (!IS_ERR(reply))
ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
else
- netlink_set_err(GENL_SOCK(sock_net(skb->sk)), 0,
+ netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
ovs_dp_flow_multicast_group.id, PTR_ERR(reply));
return 0;
};
static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
-#ifdef HAVE_NLA_NUL_STRING
[OVS_DP_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
-#endif
[OVS_DP_ATTR_UPCALL_PID] = { .type = NLA_U32 },
};
.name = OVS_DATAPATH_FAMILY,
.version = OVS_DATAPATH_VERSION,
.maxattr = OVS_DP_ATTR_MAX,
- SET_NETNSOK
+ .netnsok = true,
+ SET_PARALLEL_OPS
};
static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
return skb;
}
-static int ovs_dp_cmd_validate(struct nlattr *a[OVS_DP_ATTR_MAX + 1])
-{
- return CHECK_NUL_STRING(a[OVS_DP_ATTR_NAME], IFNAMSIZ - 1);
-}
-
/* Called with ovs_mutex. */
static struct datapath *lookup_datapath(struct net *net,
struct ovs_header *ovs_header,
if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID])
goto err;
- err = ovs_dp_cmd_validate(a);
- if (err)
- goto err;
-
ovs_lock();
err = -ENOMEM;
struct datapath *dp;
int err;
- err = ovs_dp_cmd_validate(info->attrs);
- if (err)
- return err;
-
ovs_lock();
dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
err = PTR_ERR(dp);
struct datapath *dp;
int err;
- err = ovs_dp_cmd_validate(info->attrs);
- if (err)
- return err;
-
ovs_lock();
dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
err = PTR_ERR(dp);
info->snd_seq, OVS_DP_CMD_NEW);
if (IS_ERR(reply)) {
err = PTR_ERR(reply);
- netlink_set_err(GENL_SOCK(sock_net(skb->sk)), 0,
+ netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
ovs_dp_datapath_multicast_group.id, err);
err = 0;
goto unlock;
struct datapath *dp;
int err;
- err = ovs_dp_cmd_validate(info->attrs);
- if (err)
- return err;
-
ovs_lock();
dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
if (IS_ERR(dp)) {
};
static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = {
-#ifdef HAVE_NLA_NUL_STRING
[OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
[OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
-#else
- [OVS_VPORT_ATTR_STATS] = { .minlen = sizeof(struct ovs_vport_stats) },
-#endif
[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
[OVS_VPORT_ATTR_UPCALL_PID] = { .type = NLA_U32 },
.name = OVS_VPORT_FAMILY,
.version = OVS_VPORT_VERSION,
.maxattr = OVS_VPORT_ATTR_MAX,
- SET_NETNSOK
+ .netnsok = true,
+ SET_PARALLEL_OPS
};
struct genl_multicast_group ovs_dp_vport_multicast_group = {
return skb;
}
-static int ovs_vport_cmd_validate(struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
-{
- return CHECK_NUL_STRING(a[OVS_VPORT_ATTR_NAME], IFNAMSIZ - 1);
-}
-
/* Called with ovs_mutex or RCU read lock. */
static struct vport *lookup_vport(struct net *net,
struct ovs_header *ovs_header,
!a[OVS_VPORT_ATTR_UPCALL_PID])
goto exit;
- err = ovs_vport_cmd_validate(a);
- if (err)
- goto exit;
-
ovs_lock();
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
err = -ENODEV;
struct vport *vport;
int err;
- err = ovs_vport_cmd_validate(a);
- if (err)
- goto exit;
-
ovs_lock();
vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
err = PTR_ERR(vport);
kfree_skb(reply);
exit_unlock:
ovs_unlock();
-exit:
return err;
}
struct vport *vport;
int err;
- err = ovs_vport_cmd_validate(a);
- if (err)
- goto exit;
-
ovs_lock();
vport = lookup_vport(sock_net(skb->sk), info->userhdr, a);
err = PTR_ERR(vport);
exit_unlock:
ovs_unlock();
-exit:
return err;
}
struct vport *vport;
int err;
- err = ovs_vport_cmd_validate(a);
- if (err)
- goto exit;
-
rcu_read_lock();
vport = lookup_vport(sock_net(skb->sk), ovs_header, a);
err = PTR_ERR(vport);
exit_unlock:
rcu_read_unlock();
-exit:
return err;
}
.size = sizeof(struct ovs_net),
};
+DEFINE_COMPAT_PNET_REG_FUNC(device);
+
static int __init dp_init(void)
{
int err;