diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2014-11-06 09:57:27 -0500 |
---|---|---|
committer | Pravin B Shelar <pshelar@nicira.com> | 2014-11-09 21:58:44 -0500 |
commit | e8eedb85bd238613332570ac6ae683fee94fbe36 (patch) | |
tree | a97a48cc34a9a1c911925af035011dec5ca654f3 /net/openvswitch/datapath.c | |
parent | fff06c36a2563214073707f6e6aea152713274d1 (diff) |
openvswitch: Remove redundant key ref from upcall_info.
struct dp_upcall_info has pointer to pkt_key which is already
available in OVS_CB. This also simplifies upcall handling
for gso packet.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index c2ac340e19fb..7146b38a954e 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -136,8 +136,10 @@ EXPORT_SYMBOL_GPL(lockdep_ovsl_is_held); | |||
136 | 136 | ||
137 | static struct vport *new_vport(const struct vport_parms *); | 137 | static struct vport *new_vport(const struct vport_parms *); |
138 | static int queue_gso_packets(struct datapath *dp, struct sk_buff *, | 138 | static int queue_gso_packets(struct datapath *dp, struct sk_buff *, |
139 | const struct sw_flow_key *, | ||
139 | const struct dp_upcall_info *); | 140 | const struct dp_upcall_info *); |
140 | static int queue_userspace_packet(struct datapath *dp, struct sk_buff *, | 141 | static int queue_userspace_packet(struct datapath *dp, struct sk_buff *, |
142 | const struct sw_flow_key *, | ||
141 | const struct dp_upcall_info *); | 143 | const struct dp_upcall_info *); |
142 | 144 | ||
143 | /* Must be called with rcu_read_lock. */ | 145 | /* Must be called with rcu_read_lock. */ |
@@ -271,11 +273,10 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) | |||
271 | int error; | 273 | int error; |
272 | 274 | ||
273 | upcall.cmd = OVS_PACKET_CMD_MISS; | 275 | upcall.cmd = OVS_PACKET_CMD_MISS; |
274 | upcall.key = key; | ||
275 | upcall.userdata = NULL; | 276 | upcall.userdata = NULL; |
276 | upcall.portid = ovs_vport_find_upcall_portid(p, skb); | 277 | upcall.portid = ovs_vport_find_upcall_portid(p, skb); |
277 | upcall.egress_tun_info = NULL; | 278 | upcall.egress_tun_info = NULL; |
278 | error = ovs_dp_upcall(dp, skb, &upcall); | 279 | error = ovs_dp_upcall(dp, skb, key, &upcall); |
279 | if (unlikely(error)) | 280 | if (unlikely(error)) |
280 | kfree_skb(skb); | 281 | kfree_skb(skb); |
281 | else | 282 | else |
@@ -299,6 +300,7 @@ out: | |||
299 | } | 300 | } |
300 | 301 | ||
301 | int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, | 302 | int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, |
303 | const struct sw_flow_key *key, | ||
302 | const struct dp_upcall_info *upcall_info) | 304 | const struct dp_upcall_info *upcall_info) |
303 | { | 305 | { |
304 | struct dp_stats_percpu *stats; | 306 | struct dp_stats_percpu *stats; |
@@ -310,9 +312,9 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, | |||
310 | } | 312 | } |
311 | 313 | ||
312 | if (!skb_is_gso(skb)) | 314 | if (!skb_is_gso(skb)) |
313 | err = queue_userspace_packet(dp, skb, upcall_info); | 315 | err = queue_userspace_packet(dp, skb, key, upcall_info); |
314 | else | 316 | else |
315 | err = queue_gso_packets(dp, skb, upcall_info); | 317 | err = queue_gso_packets(dp, skb, key, upcall_info); |
316 | if (err) | 318 | if (err) |
317 | goto err; | 319 | goto err; |
318 | 320 | ||
@@ -329,39 +331,43 @@ err: | |||
329 | } | 331 | } |
330 | 332 | ||
331 | static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, | 333 | static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, |
334 | const struct sw_flow_key *key, | ||
332 | const struct dp_upcall_info *upcall_info) | 335 | const struct dp_upcall_info *upcall_info) |
333 | { | 336 | { |
334 | unsigned short gso_type = skb_shinfo(skb)->gso_type; | 337 | unsigned short gso_type = skb_shinfo(skb)->gso_type; |
335 | struct dp_upcall_info later_info; | ||
336 | struct sw_flow_key later_key; | 338 | struct sw_flow_key later_key; |
337 | struct sk_buff *segs, *nskb; | 339 | struct sk_buff *segs, *nskb; |
340 | struct ovs_skb_cb ovs_cb; | ||
338 | int err; | 341 | int err; |
339 | 342 | ||
343 | ovs_cb = *OVS_CB(skb); | ||
340 | segs = __skb_gso_segment(skb, NETIF_F_SG, false); | 344 | segs = __skb_gso_segment(skb, NETIF_F_SG, false); |
345 | *OVS_CB(skb) = ovs_cb; | ||
341 | if (IS_ERR(segs)) | 346 | if (IS_ERR(segs)) |
342 | return PTR_ERR(segs); | 347 | return PTR_ERR(segs); |
343 | if (segs == NULL) | 348 | if (segs == NULL) |
344 | return -EINVAL; | 349 | return -EINVAL; |
345 | 350 | ||
351 | if (gso_type & SKB_GSO_UDP) { | ||
352 | /* The initial flow key extracted by ovs_flow_key_extract() | ||
353 | * in this case is for a first fragment, so we need to | ||
354 | * properly mark later fragments. | ||
355 | */ | ||
356 | later_key = *key; | ||
357 | later_key.ip.frag = OVS_FRAG_TYPE_LATER; | ||
358 | } | ||
359 | |||
346 | /* Queue all of the segments. */ | 360 | /* Queue all of the segments. */ |
347 | skb = segs; | 361 | skb = segs; |
348 | do { | 362 | do { |
349 | err = queue_userspace_packet(dp, skb, upcall_info); | 363 | *OVS_CB(skb) = ovs_cb; |
364 | if (gso_type & SKB_GSO_UDP && skb != segs) | ||
365 | key = &later_key; | ||
366 | |||
367 | err = queue_userspace_packet(dp, skb, key, upcall_info); | ||
350 | if (err) | 368 | if (err) |
351 | break; | 369 | break; |
352 | 370 | ||
353 | if (skb == segs && gso_type & SKB_GSO_UDP) { | ||
354 | /* The initial flow key extracted by ovs_flow_extract() | ||
355 | * in this case is for a first fragment, so we need to | ||
356 | * properly mark later fragments. | ||
357 | */ | ||
358 | later_key = *upcall_info->key; | ||
359 | later_key.ip.frag = OVS_FRAG_TYPE_LATER; | ||
360 | |||
361 | later_info = *upcall_info; | ||
362 | later_info.key = &later_key; | ||
363 | upcall_info = &later_info; | ||
364 | } | ||
365 | } while ((skb = skb->next)); | 371 | } while ((skb = skb->next)); |
366 | 372 | ||
367 | /* Free all of the segments. */ | 373 | /* Free all of the segments. */ |
@@ -395,6 +401,7 @@ static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info, | |||
395 | } | 401 | } |
396 | 402 | ||
397 | static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | 403 | static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, |
404 | const struct sw_flow_key *key, | ||
398 | const struct dp_upcall_info *upcall_info) | 405 | const struct dp_upcall_info *upcall_info) |
399 | { | 406 | { |
400 | struct ovs_header *upcall; | 407 | struct ovs_header *upcall; |
@@ -457,7 +464,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
457 | upcall->dp_ifindex = dp_ifindex; | 464 | upcall->dp_ifindex = dp_ifindex; |
458 | 465 | ||
459 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); | 466 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); |
460 | err = ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); | 467 | err = ovs_nla_put_flow(key, key, user_skb); |
461 | BUG_ON(err); | 468 | BUG_ON(err); |
462 | nla_nest_end(user_skb, nla); | 469 | nla_nest_end(user_skb, nla); |
463 | 470 | ||