History

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.

Neil McKee committed 11 years ago

Commit ccea7441 parent bdef7de4 files · +37 −10Browse files

Unified · Split

4 files
  1. include/uapi/linux/openvswitch.h +4 −0
  2. net/openvswitch/actions.c +15 −8
  3. net/openvswitch/datapath.c +16 −2
  4. net/openvswitch/datapath.h +2 −0
include/uapi/linux/openvswitch.h+4−0
@@ -153,6 +153,8 @@ enum ovs_packet_cmd { · 152 unmodified lines
153153 * flow key against the kernel's.
154154 * @OVS_PACKET_ATTR_ACTIONS: Contains actions for the packet. Used
155155 * for %OVS_PACKET_CMD_EXECUTE. It has nested %OVS_ACTION_ATTR_* attributes.
156+ * Also used in upcall when %OVS_ACTION_ATTR_USERSPACE has optional
157+ * %OVS_USERSPACE_ATTR_ACTIONS attribute.
156158 * @OVS_PACKET_ATTR_USERDATA: Present for an %OVS_PACKET_CMD_ACTION
157159 * notification if the %OVS_ACTION_ATTR_USERSPACE action specified an
158160 * %OVS_USERSPACE_ATTR_USERDATA attribute, with the same length and content
@@ -528,6 +530,7 @@ enum ovs_sample_attr { · 369 unmodified lines
528530 * copied to the %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA.
529531 * @OVS_USERSPACE_ATTR_EGRESS_TUN_PORT: If present, u32 output port to get
530532 * tunnel info.
533+ * @OVS_USERSPACE_ATTR_ACTIONS: If present, send actions with upcall.
531534 */
532535 enum ovs_userspace_attr {
533536 OVS_USERSPACE_ATTR_UNSPEC,
@@ -535,6 +538,7 @@ enum ovs_userspace_attr { · 1 unmodified line
535538 OVS_USERSPACE_ATTR_USERDATA, /* Optional user-specified cookie. */
536539 OVS_USERSPACE_ATTR_EGRESS_TUN_PORT, /* Optional, u32 output port
537540 * to get tunnel info. */
541+ OVS_USERSPACE_ATTR_ACTIONS, /* Optional flag to get actions. */
538542 __OVS_USERSPACE_ATTR_MAX
539543 };
540544
net/openvswitch/actions.c+15−8
@@ -608,17 +608,16 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port) · 607 unmodified lines
608608 }
609609
610610 static 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)
612613 {
613614 struct ovs_tunnel_info info;
614615 struct dp_upcall_info upcall;
615616 const struct nlattr *a;
616617 int rem;
617618
619+ memset(&upcall, 0, sizeof(upcall));
618620 upcall.cmd = OVS_PACKET_CMD_ACTION;
619− upcall.userdata = NULL;
620− upcall.portid = 0;
621− upcall.egress_tun_info = NULL;
622621
623622 for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
624623 a = nla_next(a, &rem)) {
@@ -647,6 +646,13 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, · 22 unmodified lines
647646 break;
648647 }
649648
649+ case OVS_USERSPACE_ATTR_ACTIONS: {
650+ /* Include actions. */
651+ upcall.actions = actions;
652+ upcall.actions_len = actions_len;
653+ break;
654+ }
655+
650656 } /* End of switch. */
651657 }
652658
@@ -654,7 +660,8 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, · 1 unmodified line
654660 }
655661
656662 static 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)
658665 {
659666 const struct nlattr *acts_list = NULL;
660667 const struct nlattr *a;
@@ -688,7 +695,7 @@ static int sample(struct datapath *dp, struct sk_buff *skb, · 27 unmodified lines
688695 */
689696 if (likely(nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
690697 nla_is_last(a, rem)))
691− return output_userspace(dp, skb, key, a);
698+ return output_userspace(dp, skb, key, a, actions, actions_len);
692699
693700 skb = skb_clone(skb, GFP_ATOMIC);
694701 if (!skb)
@@ -872,7 +879,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, · 177 unmodified lines
872879 break;
873880
874881 case OVS_ACTION_ATTR_USERSPACE:
875− output_userspace(dp, skb, key, a);
882+ output_userspace(dp, skb, key, a, attr, len);
876883 break;
877884
878885 case OVS_ACTION_ATTR_HASH:
@@ -916,7 +923,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, · 37 unmodified lines
916923 break;
917924
918925 case OVS_ACTION_ATTR_SAMPLE:
919− err = sample(dp, skb, key, a);
926+ err = sample(dp, skb, key, a, attr, len);
920927 break;
921928 }
922929
net/openvswitch/datapath.c+16−2
@@ -272,10 +272,9 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) · 271 unmodified lines
272272 struct dp_upcall_info upcall;
273273 int error;
274274
275+ memset(&upcall, 0, sizeof(upcall));
275276 upcall.cmd = OVS_PACKET_CMD_MISS;
276− upcall.userdata = NULL;
277277 upcall.portid = ovs_vport_find_upcall_portid(p, skb);
278− upcall.egress_tun_info = NULL;
279278 error = ovs_dp_upcall(dp, skb, key, &upcall);
280279 if (unlikely(error))
281280 kfree_skb(skb);
@@ -397,6 +396,10 @@ static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info, · 115 unmodified lines
397396 if (upcall_info->egress_tun_info)
398397 size += nla_total_size(ovs_tun_key_attr_size());
399398
399+ /* OVS_PACKET_ATTR_ACTIONS */
400+ if (upcall_info->actions_len)
401+ size += nla_total_size(upcall_info->actions_len);
402+
400403 return size;
401404 }
402405
@@ -478,6 +481,17 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, · 75 unmodified lines
478481 nla_nest_end(user_skb, nla);
479482 }
480483
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+
481495 /* Only reserve room for attribute header, packet data is added
482496 * in skb_zerocopy() */
483497 if (!(nla = nla_reserve(user_skb, OVS_PACKET_ATTR_PACKET, 0))) {
net/openvswitch/datapath.h+2−0
@@ -116,6 +116,8 @@ struct ovs_skb_cb { · 115 unmodified lines
116116 struct dp_upcall_info {
117117 const struct ovs_tunnel_info *egress_tun_info;
118118 const struct nlattr *userdata;
119+ const struct nlattr *actions;
120+ int actions_len;
119121 u32 portid;
120122 u8 cmd;
121123 };