- struct odp_sflow_sample_header *hdr;
- unsigned int actlen = n_actions * sizeof(union odp_action);
- unsigned int hdrlen = sizeof(struct odp_sflow_sample_header);
- struct sk_buff *nskb;
-
- nskb = skb_copy_expand(skb, actlen + hdrlen, 0, GFP_ATOMIC);
- if (!nskb)
- return;
-
- memcpy(__skb_push(nskb, actlen), a, actlen);
- hdr = (struct odp_sflow_sample_header*)__skb_push(nskb, hdrlen);
- hdr->n_actions = n_actions;
- hdr->sample_pool = atomic_read(&vport->sflow_pool);
- dp_output_control(dp, nskb, _ODPL_SFLOW_NR, 0);
+ const struct nlattr *acts_list = NULL;
+ const struct nlattr *a;
+ int rem;
+
+ for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
+ a = nla_next(a, &rem)) {
+ switch (nla_type(a)) {
+ case OVS_SAMPLE_ATTR_PROBABILITY:
+ if (net_random() >= nla_get_u32(a))
+ return 0;
+ break;
+
+ case OVS_SAMPLE_ATTR_ACTIONS:
+ acts_list = a;
+ break;
+ }
+ }
+
+ return do_execute_actions(dp, skb, nla_data(acts_list),
+ nla_len(acts_list), true);
+}
+
+static int execute_set_action(struct sk_buff *skb,
+ const struct nlattr *nested_attr)
+{
+ int err = 0;
+
+ switch (nla_type(nested_attr)) {
+ case OVS_KEY_ATTR_PRIORITY:
+ skb->priority = nla_get_u32(nested_attr);
+ break;
+
+ case OVS_KEY_ATTR_SKB_MARK:
+ skb_set_mark(skb, nla_get_u32(nested_attr));
+ break;
+
+ case OVS_KEY_ATTR_IPV4_TUNNEL:
+ OVS_CB(skb)->tun_key = nla_data(nested_attr);
+ break;
+
+ case OVS_KEY_ATTR_ETHERNET:
+ err = set_eth_addr(skb, nla_data(nested_attr));
+ break;
+
+ case OVS_KEY_ATTR_IPV4:
+ err = set_ipv4(skb, nla_data(nested_attr));
+ break;
+
+ case OVS_KEY_ATTR_IPV6:
+ err = set_ipv6(skb, nla_data(nested_attr));
+ break;
+
+ case OVS_KEY_ATTR_TCP:
+ err = set_tcp(skb, nla_data(nested_attr));
+ break;
+
+ case OVS_KEY_ATTR_UDP:
+ err = set_udp(skb, nla_data(nested_attr));
+ break;
+
+ case OVS_KEY_ATTR_SCTP:
+ err = set_sctp(skb, nla_data(nested_attr));
+ break;
+ }
+
+ return err;