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