1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.networkstack.metrics; 18 19 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_802_3_FRAME; 20 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_NON_IPV4; 21 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_OTHER_HOST; 22 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_REPLY_SPA_NO_HOST; 23 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_REQUEST_REPLIED; 24 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_UNKNOWN; 25 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ARP_V6_ONLY; 26 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ETHERTYPE_NOT_ALLOWED; 27 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ETHER_OUR_SRC_MAC; 28 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_ETH_BROADCAST; 29 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_GARP_REPLY; 30 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IGMP_INVALID; 31 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IGMP_REPORT; 32 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IGMP_V2_GENERAL_QUERY_REPLIED; 33 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IGMP_V3_GENERAL_QUERY_REPLIED; 34 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_BROADCAST_ADDR; 35 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_BROADCAST_NET; 36 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_ICMP_INVALID; 37 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_KEEPALIVE_ACK; 38 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_L2_BROADCAST; 39 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_MULTICAST; 40 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_NATT_KEEPALIVE; 41 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_NON_DHCP4; 42 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_PING_REQUEST_REPLIED; 43 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV4_TCP_PORT7_UNICAST; 44 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_ICMP6_ECHO_REQUEST_INVALID; 45 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_ICMP6_ECHO_REQUEST_REPLIED; 46 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_MLD_INVALID; 47 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_MLD_REPORT; 48 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_MLD_V1_GENERAL_QUERY_REPLIED; 49 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_MLD_V2_GENERAL_QUERY_REPLIED; 50 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_MULTICAST_NA; 51 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NON_ICMP_MULTICAST; 52 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_INVALID; 53 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_OTHER_HOST; 54 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_NS_REPLIED_NON_DAD; 55 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_IPV6_ROUTER_SOLICITATION; 56 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_MDNS; 57 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_MDNS_REPLIED; 58 import static android.net.apf.ApfCounterTracker.Counter.DROPPED_RA; 59 import static android.net.apf.ApfCounterTracker.Counter.PASSED_ARP_BROADCAST_REPLY; 60 import static android.net.apf.ApfCounterTracker.Counter.PASSED_ARP_REQUEST; 61 import static android.net.apf.ApfCounterTracker.Counter.PASSED_ARP_UNICAST_REPLY; 62 import static android.net.apf.ApfCounterTracker.Counter.PASSED_DHCP; 63 import static android.net.apf.ApfCounterTracker.Counter.PASSED_ETHER_OUR_SRC_MAC; 64 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4; 65 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4_FROM_DHCPV4_SERVER; 66 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV4_UNICAST; 67 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_HOPOPTS; 68 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_ICMP; 69 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_NON_ICMP; 70 import static android.net.apf.ApfCounterTracker.Counter.PASSED_IPV6_UNICAST_NON_ICMP; 71 import static android.net.apf.ApfCounterTracker.Counter.PASSED_NON_IP_UNICAST; 72 import static android.net.apf.ApfCounterTracker.Counter.RESERVED_OOB; 73 import static android.net.apf.ApfCounterTracker.Counter.TOTAL_PACKETS; 74 import static android.stats.connectivity.CounterName.CN_DROPPED_802_3_FRAME; 75 import static android.stats.connectivity.CounterName.CN_DROPPED_ARP_NON_IPV4; 76 import static android.stats.connectivity.CounterName.CN_DROPPED_ARP_OTHER_HOST; 77 import static android.stats.connectivity.CounterName.CN_DROPPED_ARP_REPLY_SPA_NO_HOST; 78 import static android.stats.connectivity.CounterName.CN_DROPPED_ARP_REQUEST_REPLIED; 79 import static android.stats.connectivity.CounterName.CN_DROPPED_ARP_UNKNOWN; 80 import static android.stats.connectivity.CounterName.CN_DROPPED_ARP_V6_ONLY; 81 import static android.stats.connectivity.CounterName.CN_DROPPED_ETHERTYPE_NOT_ALLOWED; 82 import static android.stats.connectivity.CounterName.CN_DROPPED_ETHER_OUR_SRC_MAC; 83 import static android.stats.connectivity.CounterName.CN_DROPPED_ETH_BROADCAST; 84 import static android.stats.connectivity.CounterName.CN_DROPPED_GARP_REPLY; 85 import static android.stats.connectivity.CounterName.CN_DROPPED_IGMP_INVALID; 86 import static android.stats.connectivity.CounterName.CN_DROPPED_IGMP_REPORT; 87 import static android.stats.connectivity.CounterName.CN_DROPPED_IGMP_V2_GENERAL_QUERY_REPLIED; 88 import static android.stats.connectivity.CounterName.CN_DROPPED_IGMP_V3_GENERAL_QUERY_REPLIED; 89 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_BROADCAST_ADDR; 90 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_BROADCAST_NET; 91 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_ICMP_INVALID; 92 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_KEEPALIVE_ACK; 93 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_L2_BROADCAST; 94 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_MULTICAST; 95 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_NATT_KEEPALIVE; 96 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_NON_DHCP4; 97 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_PING_REQUEST_REPLIED; 98 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV4_TCP_PORT7_UNICAST; 99 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_ICMP6_ECHO_REQUEST_INVALID; 100 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_ICMP6_ECHO_REQUEST_REPLIED; 101 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_MLD_INVALID; 102 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_MLD_REPORT; 103 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_MLD_V1_GENERAL_QUERY_REPLIED; 104 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_MLD_V2_GENERAL_QUERY_REPLIED; 105 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_MULTICAST_NA; 106 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_NON_ICMP_MULTICAST; 107 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_NS_INVALID; 108 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_NS_OTHER_HOST; 109 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_NS_REPLIED_NON_DAD; 110 import static android.stats.connectivity.CounterName.CN_DROPPED_IPV6_ROUTER_SOLICITATION; 111 import static android.stats.connectivity.CounterName.CN_DROPPED_MDNS; 112 import static android.stats.connectivity.CounterName.CN_DROPPED_MDNS_REPLIED; 113 import static android.stats.connectivity.CounterName.CN_DROPPED_RA; 114 import static android.stats.connectivity.CounterName.CN_PASSED_ARP_BROADCAST_REPLY; 115 import static android.stats.connectivity.CounterName.CN_PASSED_ARP_REQUEST; 116 import static android.stats.connectivity.CounterName.CN_PASSED_ARP_UNICAST_REPLY; 117 import static android.stats.connectivity.CounterName.CN_PASSED_DHCP; 118 import static android.stats.connectivity.CounterName.CN_PASSED_IPV4; 119 import static android.stats.connectivity.CounterName.CN_PASSED_IPV4_FROM_DHCPV4_SERVER; 120 import static android.stats.connectivity.CounterName.CN_PASSED_IPV4_UNICAST; 121 import static android.stats.connectivity.CounterName.CN_PASSED_IPV6_HOPOPTS; 122 import static android.stats.connectivity.CounterName.CN_PASSED_IPV6_ICMP; 123 import static android.stats.connectivity.CounterName.CN_PASSED_IPV6_NON_ICMP; 124 import static android.stats.connectivity.CounterName.CN_PASSED_IPV6_UNICAST_NON_ICMP; 125 import static android.stats.connectivity.CounterName.CN_PASSED_NON_IP_UNICAST; 126 import static android.stats.connectivity.CounterName.CN_PASSED_OUR_SRC_MAC; 127 import static android.stats.connectivity.CounterName.CN_TOTAL_PACKETS; 128 import static android.stats.connectivity.CounterName.CN_UNKNOWN; 129 130 import android.net.apf.ApfCounterTracker.Counter; 131 import android.stats.connectivity.CounterName; 132 133 import androidx.annotation.VisibleForTesting; 134 135 import java.util.EnumMap; 136 import java.util.Map; 137 138 /** 139 * Class to record the network stack ApfSessionInfo metrics into statsd. 140 * 141 * This class is not thread-safe, and should always be accessed from the same thread. 142 * 143 * @hide 144 */ 145 public class ApfSessionInfoMetrics { 146 // Define the maximum size of the counter list 147 public static final int MAX_NUM_OF_COUNTERS = Counter.class.getEnumConstants().length - 1; 148 private static final EnumMap<Counter, CounterName> apfCounterMetricsMap = new EnumMap<>( 149 Map.ofEntries( 150 Map.entry(RESERVED_OOB, CN_UNKNOWN), 151 Map.entry(TOTAL_PACKETS, CN_TOTAL_PACKETS), 152 // The counter sequence should be keep the same in ApfCounterTracker.java 153 Map.entry(PASSED_ARP_BROADCAST_REPLY, CN_PASSED_ARP_BROADCAST_REPLY), 154 Map.entry(PASSED_ARP_REQUEST, CN_PASSED_ARP_REQUEST), 155 Map.entry(PASSED_ARP_UNICAST_REPLY, CN_PASSED_ARP_UNICAST_REPLY), 156 Map.entry(PASSED_DHCP, CN_PASSED_DHCP), 157 Map.entry(PASSED_ETHER_OUR_SRC_MAC, CN_PASSED_OUR_SRC_MAC), 158 Map.entry(PASSED_IPV4, CN_PASSED_IPV4), 159 Map.entry(PASSED_IPV4_FROM_DHCPV4_SERVER, CN_PASSED_IPV4_FROM_DHCPV4_SERVER), 160 Map.entry(PASSED_IPV4_UNICAST, CN_PASSED_IPV4_UNICAST), 161 Map.entry(PASSED_IPV6_HOPOPTS, CN_PASSED_IPV6_HOPOPTS), 162 Map.entry(PASSED_IPV6_ICMP, CN_PASSED_IPV6_ICMP), 163 Map.entry(PASSED_IPV6_NON_ICMP, CN_PASSED_IPV6_NON_ICMP), 164 Map.entry(PASSED_IPV6_UNICAST_NON_ICMP, CN_PASSED_IPV6_UNICAST_NON_ICMP), 165 Map.entry(PASSED_NON_IP_UNICAST, CN_PASSED_NON_IP_UNICAST), 166 Map.entry(DROPPED_ETH_BROADCAST, CN_DROPPED_ETH_BROADCAST), 167 Map.entry(DROPPED_ETHER_OUR_SRC_MAC, CN_DROPPED_ETHER_OUR_SRC_MAC), 168 Map.entry(DROPPED_RA, CN_DROPPED_RA), 169 Map.entry(DROPPED_IPV4_L2_BROADCAST, CN_DROPPED_IPV4_L2_BROADCAST), 170 Map.entry(DROPPED_IPV4_BROADCAST_ADDR, CN_DROPPED_IPV4_BROADCAST_ADDR), 171 Map.entry(DROPPED_IPV4_BROADCAST_NET, CN_DROPPED_IPV4_BROADCAST_NET), 172 Map.entry(DROPPED_IPV4_ICMP_INVALID, CN_DROPPED_IPV4_ICMP_INVALID), 173 Map.entry(DROPPED_IPV4_MULTICAST, CN_DROPPED_IPV4_MULTICAST), 174 Map.entry(DROPPED_IPV4_NON_DHCP4, CN_DROPPED_IPV4_NON_DHCP4), 175 Map.entry(DROPPED_IPV4_PING_REQUEST_REPLIED, CN_DROPPED_IPV4_PING_REQUEST_REPLIED), 176 Map.entry(DROPPED_IPV6_ICMP6_ECHO_REQUEST_INVALID, 177 CN_DROPPED_IPV6_ICMP6_ECHO_REQUEST_INVALID), 178 Map.entry(DROPPED_IPV6_ICMP6_ECHO_REQUEST_REPLIED, 179 CN_DROPPED_IPV6_ICMP6_ECHO_REQUEST_REPLIED), 180 Map.entry(DROPPED_IPV6_ROUTER_SOLICITATION, CN_DROPPED_IPV6_ROUTER_SOLICITATION), 181 Map.entry(DROPPED_IPV6_MLD_INVALID, CN_DROPPED_IPV6_MLD_INVALID), 182 Map.entry(DROPPED_IPV6_MLD_REPORT, CN_DROPPED_IPV6_MLD_REPORT), 183 Map.entry(DROPPED_IPV6_MLD_V1_GENERAL_QUERY_REPLIED, 184 CN_DROPPED_IPV6_MLD_V1_GENERAL_QUERY_REPLIED), 185 Map.entry(DROPPED_IPV6_MLD_V2_GENERAL_QUERY_REPLIED, 186 CN_DROPPED_IPV6_MLD_V2_GENERAL_QUERY_REPLIED), 187 Map.entry(DROPPED_IPV6_MULTICAST_NA, CN_DROPPED_IPV6_MULTICAST_NA), 188 Map.entry(DROPPED_IPV6_NON_ICMP_MULTICAST, CN_DROPPED_IPV6_NON_ICMP_MULTICAST), 189 Map.entry(DROPPED_IPV6_NS_INVALID, CN_DROPPED_IPV6_NS_INVALID), 190 Map.entry(DROPPED_IPV6_NS_OTHER_HOST, CN_DROPPED_IPV6_NS_OTHER_HOST), 191 Map.entry(DROPPED_IPV6_NS_REPLIED_NON_DAD, CN_DROPPED_IPV6_NS_REPLIED_NON_DAD), 192 Map.entry(DROPPED_802_3_FRAME, CN_DROPPED_802_3_FRAME), 193 Map.entry(DROPPED_ETHERTYPE_NOT_ALLOWED, CN_DROPPED_ETHERTYPE_NOT_ALLOWED), 194 Map.entry(DROPPED_IPV4_KEEPALIVE_ACK, CN_DROPPED_IPV4_KEEPALIVE_ACK), 195 Map.entry(DROPPED_IPV4_NATT_KEEPALIVE, CN_DROPPED_IPV4_NATT_KEEPALIVE), 196 Map.entry(DROPPED_MDNS, CN_DROPPED_MDNS), 197 Map.entry(DROPPED_MDNS_REPLIED, CN_DROPPED_MDNS_REPLIED), 198 Map.entry(DROPPED_IPV4_TCP_PORT7_UNICAST, CN_DROPPED_IPV4_TCP_PORT7_UNICAST), 199 Map.entry(DROPPED_ARP_NON_IPV4, CN_DROPPED_ARP_NON_IPV4), 200 Map.entry(DROPPED_ARP_OTHER_HOST, CN_DROPPED_ARP_OTHER_HOST), 201 Map.entry(DROPPED_ARP_REPLY_SPA_NO_HOST, CN_DROPPED_ARP_REPLY_SPA_NO_HOST), 202 Map.entry(DROPPED_ARP_REQUEST_REPLIED, CN_DROPPED_ARP_REQUEST_REPLIED), 203 Map.entry(DROPPED_ARP_UNKNOWN, CN_DROPPED_ARP_UNKNOWN), 204 Map.entry(DROPPED_ARP_V6_ONLY, CN_DROPPED_ARP_V6_ONLY), 205 Map.entry(DROPPED_IGMP_V2_GENERAL_QUERY_REPLIED, 206 CN_DROPPED_IGMP_V2_GENERAL_QUERY_REPLIED), 207 Map.entry(DROPPED_IGMP_V3_GENERAL_QUERY_REPLIED, 208 CN_DROPPED_IGMP_V3_GENERAL_QUERY_REPLIED), 209 Map.entry(DROPPED_IGMP_INVALID, CN_DROPPED_IGMP_INVALID), 210 Map.entry(DROPPED_IGMP_REPORT, CN_DROPPED_IGMP_REPORT), 211 Map.entry(DROPPED_GARP_REPLY, CN_DROPPED_GARP_REPLY) 212 ) 213 ); 214 private final ApfSessionInfoReported.Builder mStatsBuilder = 215 ApfSessionInfoReported.newBuilder(); 216 private final ApfCounterList.Builder mApfCounterListBuilder = ApfCounterList.newBuilder(); 217 218 /** 219 * Write the version to mStatsBuilder. 220 */ setVersion(final int version)221 public void setVersion(final int version) { 222 mStatsBuilder.setVersion(version); 223 } 224 225 /** 226 * Write the memory size to mStatsBuilder. 227 */ setMemorySize(final int memorySize)228 public void setMemorySize(final int memorySize) { 229 mStatsBuilder.setMemorySize(memorySize); 230 } 231 232 /** 233 * Add an APF counter to the metrics builder. 234 */ addApfCounter(final Counter counter, final long value)235 public void addApfCounter(final Counter counter, final long value) { 236 if (mApfCounterListBuilder.getApfCounterCount() >= MAX_NUM_OF_COUNTERS) return; 237 final ApfCounter.Builder apfCounterBuilder = ApfCounter.newBuilder() 238 .setCounterName(apfFilterCounterToEnum(counter)) 239 .setCounterValue(value); 240 241 mApfCounterListBuilder.addApfCounter(apfCounterBuilder); 242 } 243 244 /** 245 * Write the session duration to mStatsBuilder. 246 */ setApfSessionDurationSeconds(final int durationSeconds)247 public void setApfSessionDurationSeconds(final int durationSeconds) { 248 mStatsBuilder.setApfSessionDurationSeconds(durationSeconds); 249 } 250 251 /** 252 * Write the number of times APF program updated to mStatsBuilder. 253 */ setNumOfTimesApfProgramUpdated(final int updatedTimes)254 public void setNumOfTimesApfProgramUpdated(final int updatedTimes) { 255 mStatsBuilder.setNumOfTimesApfProgramUpdated(updatedTimes); 256 } 257 258 /** 259 * Write the maximum program size to mStatsBuilder. 260 */ setMaxProgramSize(final int programSize)261 public void setMaxProgramSize(final int programSize) { 262 mStatsBuilder.setMaxProgramSize(programSize); 263 } 264 265 /** 266 * Write the ApfSessionInfoReported proto into statsd. 267 */ statsWrite()268 public ApfSessionInfoReported statsWrite() { 269 mStatsBuilder.setApfCounterList(mApfCounterListBuilder); 270 final ApfSessionInfoReported stats = mStatsBuilder.build(); 271 final byte[] apfCounterList = stats.getApfCounterList().toByteArray(); 272 NetworkStackStatsLog.write(NetworkStackStatsLog.APF_SESSION_INFO_REPORTED, 273 stats.getVersion(), 274 stats.getMemorySize(), 275 apfCounterList, 276 stats.getApfSessionDurationSeconds(), 277 stats.getNumOfTimesApfProgramUpdated(), 278 stats.getMaxProgramSize()); 279 return stats; 280 } 281 282 /** 283 * Map ApfCounterTracker.Counter to {@link CounterName}. 284 */ 285 @VisibleForTesting apfFilterCounterToEnum(final Counter counter)286 public static CounterName apfFilterCounterToEnum(final Counter counter) { 287 return apfCounterMetricsMap.getOrDefault(counter, CN_UNKNOWN); 288 } 289 } 290