psample: Add additional metadata attributes
authorIdo Schimmel <idosch@nvidia.com>
Sun, 14 Mar 2021 12:19:31 +0000 (14:19 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 14 Mar 2021 22:00:43 +0000 (15:00 -0700)
Extend psample to report the following attributes when available:

* Output traffic class as a 16-bit value
* Output traffic class occupancy in bytes as a 64-bit value
* End-to-end latency of the packet in nanoseconds resolution
* Software timestamp in nanoseconds resolution (always available)
* Packet's protocol. Needed for packet dissection in user space (always
  available)

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/psample.h
include/uapi/linux/psample.h
net/psample/psample.c

index ac6dbfb..e328c51 100644 (file)
@@ -18,6 +18,13 @@ struct psample_metadata {
        u32 trunc_size;
        int in_ifindex;
        int out_ifindex;
+       u16 out_tc;
+       u64 out_tc_occ; /* bytes */
+       u64 latency;    /* nanoseconds */
+       u8 out_tc_valid:1,
+          out_tc_occ_valid:1,
+          latency_valid:1,
+          unused:5;
 };
 
 struct psample_group *psample_group_get(struct net *net, u32 group_num);
index aea26ab..c6329f7 100644 (file)
@@ -16,6 +16,13 @@ enum {
        /* commands attributes */
        PSAMPLE_ATTR_GROUP_REFCOUNT,
 
+       PSAMPLE_ATTR_PAD,
+       PSAMPLE_ATTR_OUT_TC,            /* u16 */
+       PSAMPLE_ATTR_OUT_TC_OCC,        /* u64, bytes */
+       PSAMPLE_ATTR_LATENCY,           /* u64, nanoseconds */
+       PSAMPLE_ATTR_TIMESTAMP,         /* u64, nanoseconds */
+       PSAMPLE_ATTR_PROTO,             /* u16 */
+
        __PSAMPLE_ATTR_MAX
 };
 
index 065bc88..118d5d2 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/module.h>
+#include <linux/timekeeping.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -358,6 +359,7 @@ static int psample_tunnel_meta_len(struct ip_tunnel_info *tun_info)
 void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
                           u32 sample_rate, const struct psample_metadata *md)
 {
+       ktime_t tstamp = ktime_get_real();
        int out_ifindex = md->out_ifindex;
        int in_ifindex = md->in_ifindex;
        u32 trunc_size = md->trunc_size;
@@ -372,10 +374,15 @@ void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
 
        meta_len = (in_ifindex ? nla_total_size(sizeof(u16)) : 0) +
                   (out_ifindex ? nla_total_size(sizeof(u16)) : 0) +
+                  (md->out_tc_valid ? nla_total_size(sizeof(u16)) : 0) +
+                  (md->out_tc_occ_valid ? nla_total_size_64bit(sizeof(u64)) : 0) +
+                  (md->latency_valid ? nla_total_size_64bit(sizeof(u64)) : 0) +
                   nla_total_size(sizeof(u32)) +        /* sample_rate */
                   nla_total_size(sizeof(u32)) +        /* orig_size */
                   nla_total_size(sizeof(u32)) +        /* group_num */
-                  nla_total_size(sizeof(u32));         /* seq */
+                  nla_total_size(sizeof(u32)) +        /* seq */
+                  nla_total_size_64bit(sizeof(u64)) +  /* timestamp */
+                  nla_total_size(sizeof(u16));         /* protocol */
 
 #ifdef CONFIG_INET
        tun_info = skb_tunnel_info(skb);
@@ -425,6 +432,36 @@ void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
        if (unlikely(ret < 0))
                goto error;
 
+       if (md->out_tc_valid) {
+               ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_OUT_TC, md->out_tc);
+               if (unlikely(ret < 0))
+                       goto error;
+       }
+
+       if (md->out_tc_occ_valid) {
+               ret = nla_put_u64_64bit(nl_skb, PSAMPLE_ATTR_OUT_TC_OCC,
+                                       md->out_tc_occ, PSAMPLE_ATTR_PAD);
+               if (unlikely(ret < 0))
+                       goto error;
+       }
+
+       if (md->latency_valid) {
+               ret = nla_put_u64_64bit(nl_skb, PSAMPLE_ATTR_LATENCY,
+                                       md->latency, PSAMPLE_ATTR_PAD);
+               if (unlikely(ret < 0))
+                       goto error;
+       }
+
+       ret = nla_put_u64_64bit(nl_skb, PSAMPLE_ATTR_TIMESTAMP,
+                               ktime_to_ns(tstamp), PSAMPLE_ATTR_PAD);
+       if (unlikely(ret < 0))
+               goto error;
+
+       ret = nla_put_u16(nl_skb, PSAMPLE_ATTR_PROTO,
+                         be16_to_cpu(skb->protocol));
+       if (unlikely(ret < 0))
+               goto error;
+
        if (data_len) {
                int nla_len = nla_total_size(data_len);
                struct nlattr *nla;