]> www.infradead.org Git - nvme.git/commitdiff
net: openvswitch: store sampling probability in cb.
authorAdrian Moreno <amorenoz@redhat.com>
Thu, 4 Jul 2024 08:56:57 +0000 (10:56 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 6 Jul 2024 00:45:47 +0000 (17:45 -0700)
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: Aaron Conole <aconole@redhat.com>
Acked-by: Eelco Chaudron <echaudro@redhat.com>
Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
Link: https://patch.msgid.link/20240704085710.353845-7-amorenoz@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/uapi/linux/openvswitch.h
net/openvswitch/actions.c
net/openvswitch/datapath.h
net/openvswitch/vport.c

index 3dd653748725bc15c4545d96b6d77b6df58b064d..3a701bd1f31bd0861c0f7ec4a9d6ce92b0efd7d5 100644 (file)
@@ -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,
index 892d7e48fc5b1c2a10ece69ca30d5a0d7b93c011..101f9a23792c4917f9ac7b281a98a993762637ad 100644 (file)
@@ -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,
-                            clone_flow_key);
+       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,
index 0cd29971a907cabe1436703e90386889e77a14d8..9ca6231ea647037ae8162acee0dc17286112e8a5 100644 (file)
@@ -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)
 
index 972ae01a70f766910a88309b298b988d28439f84..8732f6e51ae5a0b795817c408ac0f220870e245f 100644 (file)
@@ -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;