diff options
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 6cfb44f3a7f0..c2ac340e19fb 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -274,6 +274,7 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) | |||
274 | upcall.key = key; | 274 | upcall.key = key; |
275 | upcall.userdata = NULL; | 275 | upcall.userdata = NULL; |
276 | upcall.portid = ovs_vport_find_upcall_portid(p, skb); | 276 | upcall.portid = ovs_vport_find_upcall_portid(p, skb); |
277 | upcall.egress_tun_info = NULL; | ||
277 | error = ovs_dp_upcall(dp, skb, &upcall); | 278 | error = ovs_dp_upcall(dp, skb, &upcall); |
278 | if (unlikely(error)) | 279 | if (unlikely(error)) |
279 | kfree_skb(skb); | 280 | kfree_skb(skb); |
@@ -375,7 +376,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb, | |||
375 | return err; | 376 | return err; |
376 | } | 377 | } |
377 | 378 | ||
378 | static size_t upcall_msg_size(const struct nlattr *userdata, | 379 | static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info, |
379 | unsigned int hdrlen) | 380 | unsigned int hdrlen) |
380 | { | 381 | { |
381 | size_t size = NLMSG_ALIGN(sizeof(struct ovs_header)) | 382 | size_t size = NLMSG_ALIGN(sizeof(struct ovs_header)) |
@@ -383,8 +384,12 @@ static size_t upcall_msg_size(const struct nlattr *userdata, | |||
383 | + nla_total_size(ovs_key_attr_size()); /* OVS_PACKET_ATTR_KEY */ | 384 | + nla_total_size(ovs_key_attr_size()); /* OVS_PACKET_ATTR_KEY */ |
384 | 385 | ||
385 | /* OVS_PACKET_ATTR_USERDATA */ | 386 | /* OVS_PACKET_ATTR_USERDATA */ |
386 | if (userdata) | 387 | if (upcall_info->userdata) |
387 | size += NLA_ALIGN(userdata->nla_len); | 388 | size += NLA_ALIGN(upcall_info->userdata->nla_len); |
389 | |||
390 | /* OVS_PACKET_ATTR_EGRESS_TUN_KEY */ | ||
391 | if (upcall_info->egress_tun_info) | ||
392 | size += nla_total_size(ovs_tun_key_attr_size()); | ||
388 | 393 | ||
389 | return size; | 394 | return size; |
390 | } | 395 | } |
@@ -440,7 +445,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
440 | else | 445 | else |
441 | hlen = skb->len; | 446 | hlen = skb->len; |
442 | 447 | ||
443 | len = upcall_msg_size(upcall_info->userdata, hlen); | 448 | len = upcall_msg_size(upcall_info, hlen); |
444 | user_skb = genlmsg_new_unicast(len, &info, GFP_ATOMIC); | 449 | user_skb = genlmsg_new_unicast(len, &info, GFP_ATOMIC); |
445 | if (!user_skb) { | 450 | if (!user_skb) { |
446 | err = -ENOMEM; | 451 | err = -ENOMEM; |
@@ -461,6 +466,14 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
461 | nla_len(upcall_info->userdata), | 466 | nla_len(upcall_info->userdata), |
462 | nla_data(upcall_info->userdata)); | 467 | nla_data(upcall_info->userdata)); |
463 | 468 | ||
469 | if (upcall_info->egress_tun_info) { | ||
470 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); | ||
471 | err = ovs_nla_put_egress_tunnel_key(user_skb, | ||
472 | upcall_info->egress_tun_info); | ||
473 | BUG_ON(err); | ||
474 | nla_nest_end(user_skb, nla); | ||
475 | } | ||
476 | |||
464 | /* Only reserve room for attribute header, packet data is added | 477 | /* Only reserve room for attribute header, packet data is added |
465 | * in skb_zerocopy() */ | 478 | * in skb_zerocopy() */ |
466 | if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) { | 479 | if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) { |