162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci=============================================== 462306a36Sopenharmony_ciGeneric networking statistics for netlink users 562306a36Sopenharmony_ci=============================================== 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciStatistic counters are grouped into structs: 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci==================== ===================== ===================== 1062306a36Sopenharmony_ciStruct TLV type Description 1162306a36Sopenharmony_ci==================== ===================== ===================== 1262306a36Sopenharmony_cignet_stats_basic TCA_STATS_BASIC Basic statistics 1362306a36Sopenharmony_cignet_stats_rate_est TCA_STATS_RATE_EST Rate estimator 1462306a36Sopenharmony_cignet_stats_queue TCA_STATS_QUEUE Queue statistics 1562306a36Sopenharmony_cinone TCA_STATS_APP Application specific 1662306a36Sopenharmony_ci==================== ===================== ===================== 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciCollecting: 2062306a36Sopenharmony_ci----------- 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciDeclare the statistic structs you need:: 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci struct mystruct { 2562306a36Sopenharmony_ci struct gnet_stats_basic bstats; 2662306a36Sopenharmony_ci struct gnet_stats_queue qstats; 2762306a36Sopenharmony_ci ... 2862306a36Sopenharmony_ci }; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciUpdate statistics, in dequeue() methods only, (while owning qdisc->running):: 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci mystruct->tstats.packet++; 3362306a36Sopenharmony_ci mystruct->qstats.backlog += skb->pkt_len; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciExport to userspace (Dump): 3762306a36Sopenharmony_ci--------------------------- 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci:: 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci my_dumping_routine(struct sk_buff *skb, ...) 4262306a36Sopenharmony_ci { 4362306a36Sopenharmony_ci struct gnet_dump dump; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump, 4662306a36Sopenharmony_ci TCA_PAD) < 0) 4762306a36Sopenharmony_ci goto rtattr_failure; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 || 5062306a36Sopenharmony_ci gnet_stats_copy_queue(&dump, &mystruct->qstats) < 0 || 5162306a36Sopenharmony_ci gnet_stats_copy_app(&dump, &xstats, sizeof(xstats)) < 0) 5262306a36Sopenharmony_ci goto rtattr_failure; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (gnet_stats_finish_copy(&dump) < 0) 5562306a36Sopenharmony_ci goto rtattr_failure; 5662306a36Sopenharmony_ci ... 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciTCA_STATS/TCA_XSTATS backward compatibility: 6062306a36Sopenharmony_ci-------------------------------------------- 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ciPrior users of struct tc_stats and xstats can maintain backward 6362306a36Sopenharmony_cicompatibility by calling the compat wrappers to keep providing the 6462306a36Sopenharmony_ciexisting TLV types:: 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci my_dumping_routine(struct sk_buff *skb, ...) 6762306a36Sopenharmony_ci { 6862306a36Sopenharmony_ci if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, 6962306a36Sopenharmony_ci TCA_XSTATS, &mystruct->lock, &dump, 7062306a36Sopenharmony_ci TCA_PAD) < 0) 7162306a36Sopenharmony_ci goto rtattr_failure; 7262306a36Sopenharmony_ci ... 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciA struct tc_stats will be filled out during gnet_stats_copy_* calls 7662306a36Sopenharmony_ciand appended to the skb. TCA_XSTATS is provided if gnet_stats_copy_app 7762306a36Sopenharmony_ciwas called. 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ciLocking: 8162306a36Sopenharmony_ci-------- 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciLocks are taken before writing and released once all statistics have 8462306a36Sopenharmony_cibeen written. Locks are always released in case of an error. You 8562306a36Sopenharmony_ciare responsible for making sure that the lock is initialized. 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ciRate Estimator: 8962306a36Sopenharmony_ci--------------- 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci0) Prepare an estimator attribute. Most likely this would be in user 9262306a36Sopenharmony_ci space. The value of this TLV should contain a tc_estimator structure. 9362306a36Sopenharmony_ci As usual, such a TLV needs to be 32 bit aligned and therefore the 9462306a36Sopenharmony_ci length needs to be appropriately set, etc. The estimator interval 9562306a36Sopenharmony_ci and ewma log need to be converted to the appropriate values. 9662306a36Sopenharmony_ci tc_estimator.c::tc_setup_estimator() is advisable to be used as the 9762306a36Sopenharmony_ci conversion routine. It does a few clever things. It takes a time 9862306a36Sopenharmony_ci interval in microsecs, a time constant also in microsecs and a struct 9962306a36Sopenharmony_ci tc_estimator to be populated. The returned tc_estimator can be 10062306a36Sopenharmony_ci transported to the kernel. Transfer such a structure in a TLV of type 10162306a36Sopenharmony_ci TCA_RATE to your code in the kernel. 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciIn the kernel when setting up: 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci1) make sure you have basic stats and rate stats setup first. 10662306a36Sopenharmony_ci2) make sure you have initialized stats lock that is used to setup such 10762306a36Sopenharmony_ci stats. 10862306a36Sopenharmony_ci3) Now initialize a new estimator:: 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci int ret = gen_new_estimator(my_basicstats,my_rate_est_stats, 11162306a36Sopenharmony_ci mystats_lock, attr_with_tcestimator_struct); 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if ret == 0 11462306a36Sopenharmony_ci success 11562306a36Sopenharmony_ci else 11662306a36Sopenharmony_ci failed 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ciFrom now on, every time you dump my_rate_est_stats it will contain 11962306a36Sopenharmony_ciup-to-date info. 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ciOnce you are done, call gen_kill_estimator(my_basicstats, 12262306a36Sopenharmony_cimy_rate_est_stats) Make sure that my_basicstats and my_rate_est_stats 12362306a36Sopenharmony_ciare still valid (i.e still exist) at the time of making this call. 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ciAuthors: 12762306a36Sopenharmony_ci-------- 12862306a36Sopenharmony_ci- Thomas Graf <tgraf@suug.ch> 12962306a36Sopenharmony_ci- Jamal Hadi Salim <hadi@cyberus.ca> 130