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
153 * flow key against the kernel's.153 * flow key against the kernel's.
154 * @OVS_PACKET_ATTR_ACTIONS: Contains actions for the packet. Used154 * @OVS_PACKET_ATTR_ACTIONS: Contains actions for the packet. Used
155 * for %OVS_PACKET_CMD_EXECUTE. It has nested %OVS_ACTION_ATTR_* attributes.155 * 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.
156 * @OVS_PACKET_ATTR_USERDATA: Present for an %OVS_PACKET_CMD_ACTION158 * @OVS_PACKET_ATTR_USERDATA: Present for an %OVS_PACKET_CMD_ACTION
157 * notification if the %OVS_ACTION_ATTR_USERSPACE action specified an159 * notification if the %OVS_ACTION_ATTR_USERSPACE action specified an
158 * %OVS_USERSPACE_ATTR_USERDATA attribute, with the same length and content160 * %OVS_USERSPACE_ATTR_USERDATA attribute, with the same length and content
@@ -528,6 +530,7 @@ enum ovs_sample_attr { · 369 unmodified lines
528 * copied to the %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA.530 * copied to the %OVS_PACKET_CMD_ACTION message as %OVS_PACKET_ATTR_USERDATA.
529 * @OVS_USERSPACE_ATTR_EGRESS_TUN_PORT: If present, u32 output port to get531 * @OVS_USERSPACE_ATTR_EGRESS_TUN_PORT: If present, u32 output port to get
530 * tunnel info.532 * tunnel info.
533 * @OVS_USERSPACE_ATTR_ACTIONS: If present, send actions with upcall.
531 */534 */
532enum ovs_userspace_attr {535enum ovs_userspace_attr {
533 OVS_USERSPACE_ATTR_UNSPEC,536 OVS_USERSPACE_ATTR_UNSPEC,
@@ -535,6 +538,7 @@ enum ovs_userspace_attr { · 1 unmodified line
535 OVS_USERSPACE_ATTR_USERDATA, /* Optional user-specified cookie. */538 OVS_USERSPACE_ATTR_USERDATA, /* Optional user-specified cookie. */
536 OVS_USERSPACE_ATTR_EGRESS_TUN_PORT, /* Optional, u32 output port539 OVS_USERSPACE_ATTR_EGRESS_TUN_PORT, /* Optional, u32 output port
537 * to get tunnel info. */540 * to get tunnel info. */
541 OVS_USERSPACE_ATTR_ACTIONS, /* Optional flag to get actions. */
538 __OVS_USERSPACE_ATTR_MAX542 __OVS_USERSPACE_ATTR_MAX
539};543};
540 544
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
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, · 22 unmodified lines
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, · 1 unmodified line
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, · 27 unmodified lines
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, · 177 unmodified lines
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, · 37 unmodified lines
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
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
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, · 115 unmodified lines
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, · 75 unmodified lines
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 added495 /* 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))) {
net/openvswitch/datapath.h+2−0
@@ -116,6 +116,8 @@ struct ovs_skb_cb { · 115 unmodified lines
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};