Merge "metric: fix incorrect function to remove suffix string"
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index 38a6b1c..dd718ef 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -451,5 +451,6 @@
     SdeSdePerfUpdateBusFtraceEvent sde_sde_perf_update_bus = 358;
     RssStatThrottledFtraceEvent rss_stat_throttled = 359;
     NetifReceiveSkbFtraceEvent netif_receive_skb = 360;
+    NetDevXmitFtraceEvent net_dev_xmit = 361;
   }
 }
diff --git a/protos/perfetto/trace/ftrace/net.proto b/protos/perfetto/trace/ftrace/net.proto
index 67ed3e8..e5ffbfb 100644
--- a/protos/perfetto/trace/ftrace/net.proto
+++ b/protos/perfetto/trace/ftrace/net.proto
@@ -10,3 +10,9 @@
   optional string name = 2;
   optional uint64 skbaddr = 3;
 }
+message NetDevXmitFtraceEvent {
+  optional uint32 len = 1;
+  optional string name = 2;
+  optional int32 rc = 3;
+  optional uint64 skbaddr = 4;
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index cf549a8..e9afd30 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -4888,6 +4888,12 @@
   optional string name = 2;
   optional uint64 skbaddr = 3;
 }
+message NetDevXmitFtraceEvent {
+  optional uint32 len = 1;
+  optional string name = 2;
+  optional int32 rc = 3;
+  optional uint64 skbaddr = 4;
+}
 
 // End of protos/perfetto/trace/ftrace/net.proto
 
@@ -5655,6 +5661,7 @@
     SdeSdePerfUpdateBusFtraceEvent sde_sde_perf_update_bus = 358;
     RssStatThrottledFtraceEvent rss_stat_throttled = 359;
     NetifReceiveSkbFtraceEvent netif_receive_skb = 360;
+    NetDevXmitFtraceEvent net_dev_xmit = 361;
   }
 }
 
diff --git a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
index 5e63a61..bf50559 100644
--- a/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_descriptors.cc
@@ -24,7 +24,7 @@
 namespace trace_processor {
 namespace {
 
-std::array<MessageDescriptor, 361> descriptors{{
+std::array<MessageDescriptor, 362> descriptors{{
     {nullptr, 0, {}},
     {nullptr, 0, {}},
     {nullptr, 0, {}},
@@ -3864,6 +3864,17 @@
             {"skbaddr", ProtoSchemaType::kUint64},
         },
     },
+    {
+        "net_dev_xmit",
+        4,
+        {
+            {},
+            {"len", ProtoSchemaType::kUint32},
+            {"name", ProtoSchemaType::kString},
+            {"rc", ProtoSchemaType::kInt32},
+            {"skbaddr", ProtoSchemaType::kUint64},
+        },
+    },
 }};
 
 }  // namespace
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index 403b300..186b541 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -646,6 +646,10 @@
         ParseNetifReceiveSkb(cpu, ts, data);
         break;
       }
+      case FtraceEvent::kNetDevXmitFieldNumber: {
+        ParseNetDevXmit(cpu, ts, data);
+        break;
+      }
       default:
         break;
     }
@@ -1675,5 +1679,36 @@
       .AddArg(len_key, Variadic::UnsignedInteger(evt.len()));
 }
 
+void FtraceParser::ParseNetDevXmit(uint32_t cpu,
+                                   int64_t timestamp,
+                                   protozero::ConstBytes blob) {
+  protos::pbzero::NetDevXmitFtraceEvent::Decoder evt(blob.data, blob.size);
+  base::StringView net_device = evt.name();
+  base::StackString<255> counter_name("%.*s Transmitted KB",
+                                      static_cast<int>(net_device.size()),
+                                      net_device.data());
+  StringId name = context_->storage->InternString(counter_name.string_view());
+
+  // Make sure driver took care of packet.
+  if (evt.rc() != 0) {
+    return;
+  }
+  nic_transmitted_bytes_[name] += evt.len();
+
+  uint64_t nic_transmitted_kilobytes = nic_transmitted_bytes_[name] / 1024;
+  TrackId track = context_->track_tracker->InternGlobalCounterTrack(name);
+  base::Optional<CounterId> id = context_->event_tracker->PushCounter(
+      timestamp, static_cast<double>(nic_transmitted_kilobytes), track);
+  if (!id) {
+    return;
+  }
+  // Store cpu & len as args for metrics computation
+  StringId cpu_key = context_->storage->InternString("cpu");
+  StringId len_key = context_->storage->InternString("len");
+  context_->args_tracker->AddArgsTo(*id)
+      .AddArg(cpu_key, Variadic::UnsignedInteger(cpu))
+      .AddArg(len_key, Variadic::UnsignedInteger(evt.len()));
+}
+
 }  // namespace trace_processor
 }  // namespace perfetto
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.h b/src/trace_processor/importers/ftrace/ftrace_parser.h
index 04f5ab5..c9ae2c5 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.h
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.h
@@ -155,6 +155,7 @@
   void ParseNetifReceiveSkb(uint32_t cpu,
                             int64_t timestamp,
                             protozero::ConstBytes);
+  void ParseNetDevXmit(uint32_t cpu, int64_t timestamp, protozero::ConstBytes);
 
   TraceProcessorContext* context_;
   RssStatTracker rss_stat_tracker_;
@@ -224,6 +225,9 @@
   // Record number of received bytes from the network interface card.
   std::unordered_map<StringId, uint64_t> nic_received_bytes_;
 
+  // Record number of transmitted bytes to the network interface card.
+  std::unordered_map<StringId, uint64_t> nic_transmitted_bytes_;
+
   bool has_seen_first_ftrace_packet_ = false;
 
   // Stores information about the timestamp from the metadata table which is
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index f79f4b5..6234363 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -5726,6 +5726,25 @@
        kUnsetFtraceId,
        360,
        kUnsetSize},
+      {"net_dev_xmit",
+       "net",
+       {
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "len", 1, ProtoSchemaType::kUint32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "name", 2, ProtoSchemaType::kString,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "rc", 3, ProtoSchemaType::kInt32,
+            TranslationStrategy::kInvalidTranslationStrategy},
+           {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+            "skbaddr", 4, ProtoSchemaType::kUint64,
+            TranslationStrategy::kInvalidTranslationStrategy},
+       },
+       kUnsetFtraceId,
+       361,
+       kUnsetSize},
       {"oom_score_adj_update",
        "oom",
        {
diff --git a/src/traced/probes/ftrace/test/data/synthetic/events/net/net_dev_xmit/format b/src/traced/probes/ftrace/test/data/synthetic/events/net/net_dev_xmit/format
new file mode 100644
index 0000000..1691830
--- /dev/null
+++ b/src/traced/probes/ftrace/test/data/synthetic/events/net/net_dev_xmit/format
@@ -0,0 +1,14 @@
+name: net_dev_xmit
+ID: 930
+format:
+	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
+	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
+	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
+	field:int common_pid;	offset:4;	size:4;	signed:1;
+
+	field:void * skbaddr;	offset:8;	size:8;	signed:0;
+	field:unsigned int len;	offset:16;	size:4;	signed:0;
+	field:int rc;	offset:20;	size:4;	signed:1;
+	field:__data_loc char[] name;	offset:24;	size:4;	signed:0;
+
+print fmt: "dev=%s skbaddr=%p len=%u rc=%d", __get_str(name), REC->skbaddr, REC->len, REC->rc
diff --git a/test/trace_processor/network/index b/test/trace_processor/network/index
index 73f9898..a21082a 100644
--- a/test/trace_processor/network/index
+++ b/test/trace_processor/network/index
@@ -1,3 +1,4 @@
 # Network performance
 netif_receive_skb.textproto netif_receive_skb.sql netif_receive_skb.out
+net_dev_xmit.textproto net_dev_xmit.sql net_dev_xmit.out
 netperf_metric.textproto android_netperf netperf_metric.out
diff --git a/test/trace_processor/network/net_dev_xmit.out b/test/trace_processor/network/net_dev_xmit.out
new file mode 100644
index 0000000..020428b
--- /dev/null
+++ b/test/trace_processor/network/net_dev_xmit.out
@@ -0,0 +1,5 @@
+"ts","dev","cpu","len"
+10000,"rmnet0",0,1000
+10000,"rmnet0",1,1000
+10010,"rmnet0",0,1000
+12000,"wlan0",4,1300
diff --git a/test/trace_processor/network/net_dev_xmit.sql b/test/trace_processor/network/net_dev_xmit.sql
new file mode 100644
index 0000000..8c4fcd4
--- /dev/null
+++ b/test/trace_processor/network/net_dev_xmit.sql
@@ -0,0 +1,13 @@
+SELECT
+  ts,
+  REPLACE(name, " Transmitted KB", "") AS dev,
+  EXTRACT_ARG(arg_set_id, 'cpu') AS cpu,
+  EXTRACT_ARG(arg_set_id, 'len') AS len
+FROM
+  counter AS c
+  LEFT JOIN
+  counter_track AS t
+  ON c.track_id = t.id
+WHERE
+  name GLOB "* Transmitted KB"
+ORDER BY ts;
diff --git a/test/trace_processor/network/net_dev_xmit.textproto b/test/trace_processor/network/net_dev_xmit.textproto
new file mode 100644
index 0000000..693380b
--- /dev/null
+++ b/test/trace_processor/network/net_dev_xmit.textproto
@@ -0,0 +1,70 @@
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 10000
+      pid: 200
+      net_dev_xmit {
+        name: "rmnet0"
+        len: 1000
+        rc: 0
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 1
+    event {
+      timestamp: 10000
+      pid: 300
+      net_dev_xmit {
+        name: "rmnet0"
+        len: 1000
+        rc: 0
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 0
+    event {
+      timestamp: 10010
+      pid: 400
+      net_dev_xmit {
+        name: "rmnet0"
+        len: 1000
+        rc: 0
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 1
+    event {
+      timestamp: 10011
+      pid: 500
+      net_dev_xmit {
+        name: "rmnet0"
+        len: 1000
+        rc: 16
+      }
+    }
+  }
+}
+packet {
+  ftrace_events {
+    cpu: 4
+    event {
+      timestamp: 12000
+      pid: 600
+      net_dev_xmit {
+        name: "wlan0"
+        len: 1300
+        rc: 0
+      }
+    }
+  }
+}
diff --git a/tools/ftrace_proto_gen/event_list b/tools/ftrace_proto_gen/event_list
index fd8be6a..5a0f31b 100644
--- a/tools/ftrace_proto_gen/event_list
+++ b/tools/ftrace_proto_gen/event_list
@@ -355,3 +355,4 @@
 sde/sde_perf_update_bus
 synthetic/rss_stat_throttled
 net/netif_receive_skb
+net/net_dev_xmit