/* Execute a list of actions against 'skb'. */ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb) { struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); struct loop_counter *loop; int error; struct ovs_key_ipv4_tunnel tun_key; /* Check whether we've looped too much. */ loop = &__get_cpu_var(loop_counters); if (unlikely(++loop->count > MAX_LOOPS)) loop->looping = true; if (unlikely(loop->looping)) { error = loop_suppress(dp, acts); kfree_skb(skb); goto out_loop; } OVS_CB(skb)->tun_key = NULL; error = do_execute_actions(dp, skb, acts->actions, acts->actions_len, &tun_key, false); /* Check whether sub-actions looped too much. */ if (unlikely(loop->looping)) error = loop_suppress(dp, acts); out_loop: /* Decrement loop counter. */ if (!--loop->count) loop->looping = false; return error; }
/* Execute a list of actions against 'skb'. */ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb) { struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); return do_execute_actions(dp, skb, acts->actions, acts->actions_len, false); }
static int sample(struct datapath *dp, struct sk_buff *skb, const struct nlattr *attr, struct ovs_key_ipv4_tunnel *tun_key) { 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), tun_key, true); }