Commit 71763d8a authored by Adrian Moreno's avatar Adrian Moreno Committed by Jakub Kicinski
Browse files

net: openvswitch: store sampling probability in cb.



When a packet sample is observed, the sampling rate that was used is
important to estimate the real frequency of such event.

Store the probability of the parent sample action in the skb's cb area
and use it in psample action to pass it down to psample module.

Reviewed-by: default avatarAaron Conole <aconole@redhat.com>
Acked-by: default avatarEelco Chaudron <echaudro@redhat.com>
Reviewed-by: default avatarIlya Maximets <i.maximets@ovn.org>
Signed-off-by: default avatarAdrian Moreno <amorenoz@redhat.com>
Link: https://patch.msgid.link/20240704085710.353845-7-amorenoz@redhat.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent aae0b82b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -649,7 +649,8 @@ enum ovs_flow_attr {
 * Actions are passed as nested attributes.
 *
 * Executes the specified actions with the given probability on a per-packet
 * basis.
 * basis. Nested actions will be able to access the probability value of the
 * parent @OVS_ACTION_ATTR_SAMPLE.
 */
enum ovs_sample_attr {
	OVS_SAMPLE_ATTR_UNSPEC,
+17 −3
Original line number Diff line number Diff line
@@ -1048,12 +1048,15 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
	struct nlattr *sample_arg;
	int rem = nla_len(attr);
	const struct sample_arg *arg;
	u32 init_probability;
	bool clone_flow_key;
	int err;

	/* The first action is always 'OVS_SAMPLE_ATTR_ARG'. */
	sample_arg = nla_data(attr);
	arg = nla_data(sample_arg);
	actions = nla_next(sample_arg, &rem);
	init_probability = OVS_CB(skb)->probability;

	if ((arg->probability != U32_MAX) &&
	    (!arg->probability || get_random_u32() > arg->probability)) {
@@ -1062,9 +1065,16 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
		return 0;
	}

	OVS_CB(skb)->probability = arg->probability;

	clone_flow_key = !arg->exec;
	return clone_execute(dp, skb, key, 0, actions, rem, last,
	err = clone_execute(dp, skb, key, 0, actions, rem, last,
			    clone_flow_key);

	if (!last)
		OVS_CB(skb)->probability = init_probability;

	return err;
}

/* When 'last' is true, clone() should always consume the 'skb'.
@@ -1311,6 +1321,7 @@ static void execute_psample(struct datapath *dp, struct sk_buff *skb,
	struct psample_group psample_group = {};
	struct psample_metadata md = {};
	const struct nlattr *a;
	u32 rate;
	int rem;

	nla_for_each_attr(a, nla_data(attr), nla_len(attr), rem) {
@@ -1329,8 +1340,11 @@ static void execute_psample(struct datapath *dp, struct sk_buff *skb,
	psample_group.net = ovs_dp_get_net(dp);
	md.in_ifindex = OVS_CB(skb)->input_vport->dev->ifindex;
	md.trunc_size = skb->len - OVS_CB(skb)->cutlen;
	md.rate_as_probability = 1;

	rate = OVS_CB(skb)->probability ? OVS_CB(skb)->probability : U32_MAX;

	psample_sample_packet(&psample_group, skb, 0, &md);
	psample_sample_packet(&psample_group, skb, rate, &md);
}
#else
static void execute_psample(struct datapath *dp, struct sk_buff *skb,
+3 −0
Original line number Diff line number Diff line
@@ -115,12 +115,15 @@ struct datapath {
 * fragmented.
 * @acts_origlen: The netlink size of the flow actions applied to this skb.
 * @cutlen: The number of bytes from the packet end to be removed.
 * @probability: The sampling probability that was applied to this skb; 0 means
 * no sampling has occurred; U32_MAX means 100% probability.
 */
struct ovs_skb_cb {
	struct vport		*input_vport;
	u16			mru;
	u16			acts_origlen;
	u32			cutlen;
	u32			probability;
};
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)

+1 −0
Original line number Diff line number Diff line
@@ -500,6 +500,7 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
	OVS_CB(skb)->input_vport = vport;
	OVS_CB(skb)->mru = 0;
	OVS_CB(skb)->cutlen = 0;
	OVS_CB(skb)->probability = 0;
	if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
		u32 mark;