diff options
author | David S. Miller <davem@davemloft.net> | 2014-07-16 17:09:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-16 17:09:34 -0400 |
commit | 1a98c69af1ecd97bfd1f4e4539924a9192434e36 (patch) | |
tree | a243defcf921ea174f8e43fce11d06830a6a9c36 /net/openvswitch | |
parent | 7a575f6b907ea5d207d2b5010293c189616eae34 (diff) | |
parent | b6603fe574af289dbe9eb9fb4c540bca04f5a053 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r-- | net/openvswitch/actions.c | 2 | ||||
-rw-r--r-- | net/openvswitch/datapath.c | 27 | ||||
-rw-r--r-- | net/openvswitch/flow.c | 4 | ||||
-rw-r--r-- | net/openvswitch/flow.h | 5 | ||||
-rw-r--r-- | net/openvswitch/flow_table.c | 16 | ||||
-rw-r--r-- | net/openvswitch/flow_table.h | 3 | ||||
-rw-r--r-- | net/openvswitch/vport-gre.c | 17 |
7 files changed, 55 insertions, 19 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index c36856a457ca..e70d8b18e962 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -551,6 +551,8 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, | |||
551 | 551 | ||
552 | case OVS_ACTION_ATTR_SAMPLE: | 552 | case OVS_ACTION_ATTR_SAMPLE: |
553 | err = sample(dp, skb, a); | 553 | err = sample(dp, skb, a); |
554 | if (unlikely(err)) /* skb already freed. */ | ||
555 | return err; | ||
554 | break; | 556 | break; |
555 | } | 557 | } |
556 | 558 | ||
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index fe95b6c224a7..493b5141a618 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007-2013 Nicira, Inc. | 2 | * Copyright (c) 2007-2014 Nicira, Inc. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of version 2 of the GNU General Public | 5 | * modify it under the terms of version 2 of the GNU General Public |
@@ -276,7 +276,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) | |||
276 | OVS_CB(skb)->flow = flow; | 276 | OVS_CB(skb)->flow = flow; |
277 | OVS_CB(skb)->pkt_key = &key; | 277 | OVS_CB(skb)->pkt_key = &key; |
278 | 278 | ||
279 | ovs_flow_stats_update(OVS_CB(skb)->flow, skb); | 279 | ovs_flow_stats_update(OVS_CB(skb)->flow, key.tp.flags, skb); |
280 | ovs_execute_actions(dp, skb); | 280 | ovs_execute_actions(dp, skb); |
281 | stats_counter = &stats->n_hit; | 281 | stats_counter = &stats->n_hit; |
282 | 282 | ||
@@ -889,8 +889,11 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
889 | } | 889 | } |
890 | /* The unmasked key has to be the same for flow updates. */ | 890 | /* The unmasked key has to be the same for flow updates. */ |
891 | if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) { | 891 | if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) { |
892 | error = -EEXIST; | 892 | flow = ovs_flow_tbl_lookup_exact(&dp->table, &match); |
893 | goto err_unlock_ovs; | 893 | if (!flow) { |
894 | error = -ENOENT; | ||
895 | goto err_unlock_ovs; | ||
896 | } | ||
894 | } | 897 | } |
895 | /* Update actions. */ | 898 | /* Update actions. */ |
896 | old_acts = ovsl_dereference(flow->sf_acts); | 899 | old_acts = ovsl_dereference(flow->sf_acts); |
@@ -981,16 +984,12 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
981 | goto err_unlock_ovs; | 984 | goto err_unlock_ovs; |
982 | } | 985 | } |
983 | /* Check that the flow exists. */ | 986 | /* Check that the flow exists. */ |
984 | flow = ovs_flow_tbl_lookup(&dp->table, &key); | 987 | flow = ovs_flow_tbl_lookup_exact(&dp->table, &match); |
985 | if (unlikely(!flow)) { | 988 | if (unlikely(!flow)) { |
986 | error = -ENOENT; | 989 | error = -ENOENT; |
987 | goto err_unlock_ovs; | 990 | goto err_unlock_ovs; |
988 | } | 991 | } |
989 | /* The unmasked key has to be the same for flow updates. */ | 992 | |
990 | if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) { | ||
991 | error = -EEXIST; | ||
992 | goto err_unlock_ovs; | ||
993 | } | ||
994 | /* Update actions, if present. */ | 993 | /* Update actions, if present. */ |
995 | if (likely(acts)) { | 994 | if (likely(acts)) { |
996 | old_acts = ovsl_dereference(flow->sf_acts); | 995 | old_acts = ovsl_dereference(flow->sf_acts); |
@@ -1063,8 +1062,8 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1063 | goto unlock; | 1062 | goto unlock; |
1064 | } | 1063 | } |
1065 | 1064 | ||
1066 | flow = ovs_flow_tbl_lookup(&dp->table, &key); | 1065 | flow = ovs_flow_tbl_lookup_exact(&dp->table, &match); |
1067 | if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) { | 1066 | if (!flow) { |
1068 | err = -ENOENT; | 1067 | err = -ENOENT; |
1069 | goto unlock; | 1068 | goto unlock; |
1070 | } | 1069 | } |
@@ -1113,8 +1112,8 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1113 | goto unlock; | 1112 | goto unlock; |
1114 | } | 1113 | } |
1115 | 1114 | ||
1116 | flow = ovs_flow_tbl_lookup(&dp->table, &key); | 1115 | flow = ovs_flow_tbl_lookup_exact(&dp->table, &match); |
1117 | if (unlikely(!flow || !ovs_flow_cmp_unmasked_key(flow, &match))) { | 1116 | if (unlikely(!flow)) { |
1118 | err = -ENOENT; | 1117 | err = -ENOENT; |
1119 | goto unlock; | 1118 | goto unlock; |
1120 | } | 1119 | } |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 334751cb1528..d07ab538fc9d 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -61,10 +61,10 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies) | |||
61 | 61 | ||
62 | #define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF)) | 62 | #define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF)) |
63 | 63 | ||
64 | void ovs_flow_stats_update(struct sw_flow *flow, struct sk_buff *skb) | 64 | void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags, |
65 | struct sk_buff *skb) | ||
65 | { | 66 | { |
66 | struct flow_stats *stats; | 67 | struct flow_stats *stats; |
67 | __be16 tcp_flags = flow->key.tp.flags; | ||
68 | int node = numa_node_id(); | 68 | int node = numa_node_id(); |
69 | 69 | ||
70 | stats = rcu_dereference(flow->stats[node]); | 70 | stats = rcu_dereference(flow->stats[node]); |
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index ac395d2cd821..5e5aaed3a85b 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007-2013 Nicira, Inc. | 2 | * Copyright (c) 2007-2014 Nicira, Inc. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of version 2 of the GNU General Public | 5 | * modify it under the terms of version 2 of the GNU General Public |
@@ -180,7 +180,8 @@ struct arp_eth_header { | |||
180 | unsigned char ar_tip[4]; /* target IP address */ | 180 | unsigned char ar_tip[4]; /* target IP address */ |
181 | } __packed; | 181 | } __packed; |
182 | 182 | ||
183 | void ovs_flow_stats_update(struct sw_flow *, struct sk_buff *); | 183 | void ovs_flow_stats_update(struct sw_flow *, __be16 tcp_flags, |
184 | struct sk_buff *); | ||
184 | void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *, | 185 | void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *, |
185 | unsigned long *used, __be16 *tcp_flags); | 186 | unsigned long *used, __be16 *tcp_flags); |
186 | void ovs_flow_stats_clear(struct sw_flow *); | 187 | void ovs_flow_stats_clear(struct sw_flow *); |
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c index 574c3abc9b30..cf2d853646f0 100644 --- a/net/openvswitch/flow_table.c +++ b/net/openvswitch/flow_table.c | |||
@@ -456,6 +456,22 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *tbl, | |||
456 | return ovs_flow_tbl_lookup_stats(tbl, key, &n_mask_hit); | 456 | return ovs_flow_tbl_lookup_stats(tbl, key, &n_mask_hit); |
457 | } | 457 | } |
458 | 458 | ||
459 | struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl, | ||
460 | struct sw_flow_match *match) | ||
461 | { | ||
462 | struct table_instance *ti = rcu_dereference_ovsl(tbl->ti); | ||
463 | struct sw_flow_mask *mask; | ||
464 | struct sw_flow *flow; | ||
465 | |||
466 | /* Always called under ovs-mutex. */ | ||
467 | list_for_each_entry(mask, &tbl->mask_list, list) { | ||
468 | flow = masked_flow_lookup(ti, match->key, mask); | ||
469 | if (flow && ovs_flow_cmp_unmasked_key(flow, match)) /* Found */ | ||
470 | return flow; | ||
471 | } | ||
472 | return NULL; | ||
473 | } | ||
474 | |||
459 | int ovs_flow_tbl_num_masks(const struct flow_table *table) | 475 | int ovs_flow_tbl_num_masks(const struct flow_table *table) |
460 | { | 476 | { |
461 | struct sw_flow_mask *mask; | 477 | struct sw_flow_mask *mask; |
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h index ca8a5820f615..5918bff7f3f6 100644 --- a/net/openvswitch/flow_table.h +++ b/net/openvswitch/flow_table.h | |||
@@ -76,7 +76,8 @@ struct sw_flow *ovs_flow_tbl_lookup_stats(struct flow_table *, | |||
76 | u32 *n_mask_hit); | 76 | u32 *n_mask_hit); |
77 | struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *, | 77 | struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *, |
78 | const struct sw_flow_key *); | 78 | const struct sw_flow_key *); |
79 | 79 | struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl, | |
80 | struct sw_flow_match *match); | ||
80 | bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow, | 81 | bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow, |
81 | struct sw_flow_match *match); | 82 | struct sw_flow_match *match); |
82 | 83 | ||
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index 35ec4fed09e2..f49148a07da2 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
@@ -110,6 +110,22 @@ static int gre_rcv(struct sk_buff *skb, | |||
110 | return PACKET_RCVD; | 110 | return PACKET_RCVD; |
111 | } | 111 | } |
112 | 112 | ||
113 | /* Called with rcu_read_lock and BH disabled. */ | ||
114 | static int gre_err(struct sk_buff *skb, u32 info, | ||
115 | const struct tnl_ptk_info *tpi) | ||
116 | { | ||
117 | struct ovs_net *ovs_net; | ||
118 | struct vport *vport; | ||
119 | |||
120 | ovs_net = net_generic(dev_net(skb->dev), ovs_net_id); | ||
121 | vport = rcu_dereference(ovs_net->vport_net.gre_vport); | ||
122 | |||
123 | if (unlikely(!vport)) | ||
124 | return PACKET_REJECT; | ||
125 | else | ||
126 | return PACKET_RCVD; | ||
127 | } | ||
128 | |||
113 | static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | 129 | static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) |
114 | { | 130 | { |
115 | struct net *net = ovs_dp_get_net(vport->dp); | 131 | struct net *net = ovs_dp_get_net(vport->dp); |
@@ -186,6 +202,7 @@ error: | |||
186 | 202 | ||
187 | static struct gre_cisco_protocol gre_protocol = { | 203 | static struct gre_cisco_protocol gre_protocol = { |
188 | .handler = gre_rcv, | 204 | .handler = gre_rcv, |
205 | .err_handler = gre_err, | ||
189 | .priority = 1, | 206 | .priority = 1, |
190 | }; | 207 | }; |
191 | 208 | ||