X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=48f17c0914978b203ec1c69d78968562a1d371d2;hb=b532f3f09f53e83b02caeef8414897b2dfaedff1;hp=2f02f71b647bef52b2f0e9950693067b465cd1fb;hpb=1b936472569dbaf1d6140c06789890ea01967456;p=sliver-openvswitch.git diff --git a/datapath/datapath.c b/datapath/datapath.c index 2f02f71b6..48f17c091 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -58,13 +58,12 @@ #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. + LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) +#error Kernels before 2.6.18 or after 3.9 are not supported by this version of Open vSwitch. #endif #define REHASH_FLOW_INTERVAL (10 * 60 * HZ) @@ -280,6 +279,7 @@ static struct genl_family dp_packet_genl_family = { .version = OVS_PACKET_VERSION, .maxattr = OVS_PACKET_ATTR_MAX, SET_NETNSOK + SET_PARALLEL_OPS }; int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, @@ -624,7 +624,7 @@ static int validate_and_copy_set_tun(const struct nlattr *attr, 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; @@ -972,9 +972,10 @@ static struct genl_ops dp_packet_genl_ops[] = { static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats) { + struct flow_table *table; int i; - struct flow_table *table = ovsl_dereference(dp->table); + table = rcu_dereference_check(dp->table, lockdep_ovsl_is_held()); stats->n_flows = ovs_flow_tbl_count(table); stats->n_hit = stats->n_missed = stats->n_lost = 0; @@ -1009,6 +1010,7 @@ static struct genl_family dp_flow_genl_family = { .version = OVS_FLOW_VERSION, .maxattr = OVS_FLOW_ATTR_MAX, SET_NETNSOK + SET_PARALLEL_OPS }; static struct genl_multicast_group ovs_dp_flow_multicast_group = { @@ -1064,8 +1066,8 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) 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); @@ -1126,7 +1128,6 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, 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; @@ -1156,8 +1157,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, 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; @@ -1250,7 +1250,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) { struct nlattr **a = info->attrs; struct ovs_header *ovs_header = info->userhdr; - struct sw_flow_key key; + struct sw_flow_key key, masked_key; struct sw_flow *flow = NULL; struct sw_flow_mask mask; struct sk_buff *reply; @@ -1278,9 +1278,13 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) if (IS_ERR(acts)) goto error; - error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, 0, &acts); - if (error) + ovs_flow_key_mask(&masked_key, &key, &mask); + error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], + &masked_key, 0, &acts); + if (error) { + OVS_NLERR("Flow actions may not be safe on all matching packets.\n"); goto err_kfree; + } } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { error = -EINVAL; goto error; @@ -1323,6 +1327,9 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) } clear_stats(flow); + flow->key = masked_key; + flow->unmasked_key = key; + /* Make sure mask is unique in the system */ mask_p = ovs_sw_flow_mask_find(table, &mask); if (!mask_p) { @@ -1336,11 +1343,11 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) } 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. */ - ovs_flow_insert(table, flow, &key, match.range.end); + ovs_flow_insert(table, flow); reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, info->snd_seq, OVS_FLOW_CMD_NEW); @@ -1583,6 +1590,7 @@ static struct genl_family dp_datapath_genl_family = { .version = OVS_DATAPATH_VERSION, .maxattr = OVS_DP_ATTR_MAX, SET_NETNSOK + SET_PARALLEL_OPS }; static struct genl_multicast_group ovs_dp_datapath_multicast_group = { @@ -1747,7 +1755,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) goto err_destroy_local_port; ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id); - list_add_tail(&dp->list_node, &ovs_net->dps); + list_add_tail_rcu(&dp->list_node, &ovs_net->dps); ovs_unlock(); @@ -1785,7 +1793,7 @@ static void __dp_destroy(struct datapath *dp) ovs_dp_detach_port(vport); } - list_del(&dp->list_node); + list_del_rcu(&dp->list_node); /* OVSP_LOCAL is datapath internal port. We need to make sure that * all port in datapath are destroyed first before freeing datapath. @@ -1902,8 +1910,8 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) int skip = cb->args[0]; int i = 0; - ovs_lock(); - list_for_each_entry(dp, &ovs_net->dps, list_node) { + rcu_read_lock(); + list_for_each_entry_rcu(dp, &ovs_net->dps, list_node) { if (i >= skip && ovs_dp_cmd_fill_info(dp, skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, NLM_F_MULTI, @@ -1911,7 +1919,7 @@ static int ovs_dp_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) break; i++; } - ovs_unlock(); + rcu_read_unlock(); cb->args[0] = i; @@ -1962,6 +1970,7 @@ static struct genl_family dp_vport_genl_family = { .version = OVS_VPORT_VERSION, .maxattr = OVS_VPORT_ATTR_MAX, SET_NETNSOK + SET_PARALLEL_OPS }; struct genl_multicast_group ovs_dp_vport_multicast_group = { @@ -2451,6 +2460,8 @@ static struct pernet_operations ovs_net_ops = { .size = sizeof(struct ovs_net), }; +DEFINE_COMPAT_PNET_REG_FUNC(device); + static int __init dp_init(void) { int err;