aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorNeil McKee <neil.mckee@inmon.com>2015-05-26 23:59:43 -0400
committerDavid S. Miller <davem@davemloft.net>2015-06-01 18:05:40 -0400
commitccea74457bbdafe33dce8bffcb5cb183aeb5f2bb (patch)
treeb8c195485a704d7360a59f6a42c02f820c2c4a46 /net/openvswitch
parentbdef7de4b8d9be4cf7bf5aea977f827310ab3ff0 (diff)
openvswitch: include datapath actions with sampled-packet upcall to userspace
If new optional attribute OVS_USERSPACE_ATTR_ACTIONS is added to an OVS_ACTION_ATTR_USERSPACE action, then include the datapath actions in the upcall. This Directly associates the sampled packet with the path it takes through the virtual switch. Path information currently includes mangling, encapsulation and decapsulation actions for tunneling protocols GRE, VXLAN, Geneve, MPLS and QinQ, but this extension requires no further changes to accommodate datapath actions that may be added in the future. Adding path information enhances visibility into complex virtual networks. Signed-off-by: Neil McKee <neil.mckee@inmon.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/actions.c23
-rw-r--r--net/openvswitch/datapath.c18
-rw-r--r--net/openvswitch/datapath.h2
3 files changed, 33 insertions, 10 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index b491c1c296fe..8a8c0b8b4f63 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -608,17 +608,16 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
608} 608}
609 609
610static int output_userspace(struct datapath *dp, struct sk_buff *skb, 610static int output_userspace(struct datapath *dp, struct sk_buff *skb,
611 struct sw_flow_key *key, const struct nlattr *attr) 611 struct sw_flow_key *key, const struct nlattr *attr,
612 const struct nlattr *actions, int actions_len)
612{ 613{
613 struct ovs_tunnel_info info; 614 struct ovs_tunnel_info info;
614 struct dp_upcall_info upcall; 615 struct dp_upcall_info upcall;
615 const struct nlattr *a; 616 const struct nlattr *a;
616 int rem; 617 int rem;
617 618
619 memset(&upcall, 0, sizeof(upcall));
618 upcall.cmd = OVS_PACKET_CMD_ACTION; 620 upcall.cmd = OVS_PACKET_CMD_ACTION;
619 upcall.userdata = NULL;
620 upcall.portid = 0;
621 upcall.egress_tun_info = NULL;
622 621
623 for (a = nla_data(attr), rem = nla_len(attr); rem > 0; 622 for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
624 a = nla_next(a, &rem)) { 623 a = nla_next(a, &rem)) {
@@ -647,6 +646,13 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
647 break; 646 break;
648 } 647 }
649 648
649 case OVS_USERSPACE_ATTR_ACTIONS: {
650 /* Include actions. */
651 upcall.actions = actions;
652 upcall.actions_len = actions_len;
653 break;
654 }
655
650 } /* End of switch. */ 656 } /* End of switch. */
651 } 657 }
652 658
@@ -654,7 +660,8 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
654} 660}
655 661
656static int sample(struct datapath *dp, struct sk_buff *skb, 662static int sample(struct datapath *dp, struct sk_buff *skb,
657 struct sw_flow_key *key, const struct nlattr *attr) 663 struct sw_flow_key *key, const struct nlattr *attr,
664 const struct nlattr *actions, int actions_len)
658{ 665{
659 const struct nlattr *acts_list = NULL; 666 const struct nlattr *acts_list = NULL;
660 const struct nlattr *a; 667 const struct nlattr *a;
@@ -688,7 +695,7 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
688 */ 695 */
689 if (likely(nla_type(a) == OVS_ACTION_ATTR_USERSPACE && 696 if (likely(nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
690 nla_is_last(a, rem))) 697 nla_is_last(a, rem)))
691 return output_userspace(dp, skb, key, a); 698 return output_userspace(dp, skb, key, a, actions, actions_len);
692 699
693 skb = skb_clone(skb, GFP_ATOMIC); 700 skb = skb_clone(skb, GFP_ATOMIC);
694 if (!skb) 701 if (!skb)
@@ -872,7 +879,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
872 break; 879 break;
873 880
874 case OVS_ACTION_ATTR_USERSPACE: 881 case OVS_ACTION_ATTR_USERSPACE:
875 output_userspace(dp, skb, key, a); 882 output_userspace(dp, skb, key, a, attr, len);
876 break; 883 break;
877 884
878 case OVS_ACTION_ATTR_HASH: 885 case OVS_ACTION_ATTR_HASH:
@@ -916,7 +923,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
916 break; 923 break;
917 924
918 case OVS_ACTION_ATTR_SAMPLE: 925 case OVS_ACTION_ATTR_SAMPLE:
919 err = sample(dp, skb, key, a); 926 err = sample(dp, skb, key, a, attr, len);
920 break; 927 break;
921 } 928 }
922 929
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 3b90461317ec..ff8c4a4c1609 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -272,10 +272,9 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)
272 struct dp_upcall_info upcall; 272 struct dp_upcall_info upcall;
273 int error; 273 int error;
274 274
275 memset(&upcall, 0, sizeof(upcall));
275 upcall.cmd = OVS_PACKET_CMD_MISS; 276 upcall.cmd = OVS_PACKET_CMD_MISS;
276 upcall.userdata = NULL;
277 upcall.portid = ovs_vport_find_upcall_portid(p, skb); 277 upcall.portid = ovs_vport_find_upcall_portid(p, skb);
278 upcall.egress_tun_info = NULL;
279 error = ovs_dp_upcall(dp, skb, key, &upcall); 278 error = ovs_dp_upcall(dp, skb, key, &upcall);
280 if (unlikely(error)) 279 if (unlikely(error))
281 kfree_skb(skb); 280 kfree_skb(skb);
@@ -397,6 +396,10 @@ static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
397 if (upcall_info->egress_tun_info) 396 if (upcall_info->egress_tun_info)
398 size += nla_total_size(ovs_tun_key_attr_size()); 397 size += nla_total_size(ovs_tun_key_attr_size());
399 398
399 /* OVS_PACKET_ATTR_ACTIONS */
400 if (upcall_info->actions_len)
401 size += nla_total_size(upcall_info->actions_len);
402
400 return size; 403 return size;
401} 404}
402 405
@@ -478,6 +481,17 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
478 nla_nest_end(user_skb, nla); 481 nla_nest_end(user_skb, nla);
479 } 482 }
480 483
484 if (upcall_info->actions_len) {
485 nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_ACTIONS);
486 err = ovs_nla_put_actions(upcall_info->actions,
487 upcall_info->actions_len,
488 user_skb);
489 if (!err)
490 nla_nest_end(user_skb, nla);
491 else
492 nla_nest_cancel(user_skb, nla);
493 }
494
481 /* Only reserve room for attribute header, packet data is added 495 /* Only reserve room for attribute header, packet data is added
482 * in skb_zerocopy() */ 496 * in skb_zerocopy() */
483 if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) { 497 if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) {
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 4ec4a480b147..cd691e935e08 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -116,6 +116,8 @@ struct ovs_skb_cb {
116struct dp_upcall_info { 116struct dp_upcall_info {
117 const struct ovs_tunnel_info *egress_tun_info; 117 const struct ovs_tunnel_info *egress_tun_info;
118 const struct nlattr *userdata; 118 const struct nlattr *userdata;
119 const struct nlattr *actions;
120 int actions_len;
119 u32 portid; 121 u32 portid;
120 u8 cmd; 122 u8 cmd;
121}; 123};