aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/datapath.c
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2014-11-06 09:57:27 -0500
committerPravin B Shelar <pshelar@nicira.com>2014-11-09 21:58:44 -0500
commite8eedb85bd238613332570ac6ae683fee94fbe36 (patch)
treea97a48cc34a9a1c911925af035011dec5ca654f3 /net/openvswitch/datapath.c
parentfff06c36a2563214073707f6e6aea152713274d1 (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.c45
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
137static struct vport *new_vport(const struct vport_parms *); 137static struct vport *new_vport(const struct vport_parms *);
138static int queue_gso_packets(struct datapath *dp, struct sk_buff *, 138static 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 *);
140static int queue_userspace_packet(struct datapath *dp, struct sk_buff *, 141static 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
301int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, 302int 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
331static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, 333static 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
397static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, 403static 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