1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun=============================================== 4*4882a593SmuzhiyunGeneric networking statistics for netlink users 5*4882a593Smuzhiyun=============================================== 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunStatistic counters are grouped into structs: 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun==================== ===================== ===================== 10*4882a593SmuzhiyunStruct TLV type Description 11*4882a593Smuzhiyun==================== ===================== ===================== 12*4882a593Smuzhiyungnet_stats_basic TCA_STATS_BASIC Basic statistics 13*4882a593Smuzhiyungnet_stats_rate_est TCA_STATS_RATE_EST Rate estimator 14*4882a593Smuzhiyungnet_stats_queue TCA_STATS_QUEUE Queue statistics 15*4882a593Smuzhiyunnone TCA_STATS_APP Application specific 16*4882a593Smuzhiyun==================== ===================== ===================== 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun 19*4882a593SmuzhiyunCollecting: 20*4882a593Smuzhiyun----------- 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunDeclare the statistic structs you need:: 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun struct mystruct { 25*4882a593Smuzhiyun struct gnet_stats_basic bstats; 26*4882a593Smuzhiyun struct gnet_stats_queue qstats; 27*4882a593Smuzhiyun ... 28*4882a593Smuzhiyun }; 29*4882a593Smuzhiyun 30*4882a593SmuzhiyunUpdate statistics, in dequeue() methods only, (while owning qdisc->running):: 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun mystruct->tstats.packet++; 33*4882a593Smuzhiyun mystruct->qstats.backlog += skb->pkt_len; 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun 36*4882a593SmuzhiyunExport to userspace (Dump): 37*4882a593Smuzhiyun--------------------------- 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun:: 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun my_dumping_routine(struct sk_buff *skb, ...) 42*4882a593Smuzhiyun { 43*4882a593Smuzhiyun struct gnet_dump dump; 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun if (gnet_stats_start_copy(skb, TCA_STATS2, &mystruct->lock, &dump, 46*4882a593Smuzhiyun TCA_PAD) < 0) 47*4882a593Smuzhiyun goto rtattr_failure; 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun if (gnet_stats_copy_basic(&dump, &mystruct->bstats) < 0 || 50*4882a593Smuzhiyun gnet_stats_copy_queue(&dump, &mystruct->qstats) < 0 || 51*4882a593Smuzhiyun gnet_stats_copy_app(&dump, &xstats, sizeof(xstats)) < 0) 52*4882a593Smuzhiyun goto rtattr_failure; 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun if (gnet_stats_finish_copy(&dump) < 0) 55*4882a593Smuzhiyun goto rtattr_failure; 56*4882a593Smuzhiyun ... 57*4882a593Smuzhiyun } 58*4882a593Smuzhiyun 59*4882a593SmuzhiyunTCA_STATS/TCA_XSTATS backward compatibility: 60*4882a593Smuzhiyun-------------------------------------------- 61*4882a593Smuzhiyun 62*4882a593SmuzhiyunPrior users of struct tc_stats and xstats can maintain backward 63*4882a593Smuzhiyuncompatibility by calling the compat wrappers to keep providing the 64*4882a593Smuzhiyunexisting TLV types:: 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun my_dumping_routine(struct sk_buff *skb, ...) 67*4882a593Smuzhiyun { 68*4882a593Smuzhiyun if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, 69*4882a593Smuzhiyun TCA_XSTATS, &mystruct->lock, &dump, 70*4882a593Smuzhiyun TCA_PAD) < 0) 71*4882a593Smuzhiyun goto rtattr_failure; 72*4882a593Smuzhiyun ... 73*4882a593Smuzhiyun } 74*4882a593Smuzhiyun 75*4882a593SmuzhiyunA struct tc_stats will be filled out during gnet_stats_copy_* calls 76*4882a593Smuzhiyunand appended to the skb. TCA_XSTATS is provided if gnet_stats_copy_app 77*4882a593Smuzhiyunwas called. 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun 80*4882a593SmuzhiyunLocking: 81*4882a593Smuzhiyun-------- 82*4882a593Smuzhiyun 83*4882a593SmuzhiyunLocks are taken before writing and released once all statistics have 84*4882a593Smuzhiyunbeen written. Locks are always released in case of an error. You 85*4882a593Smuzhiyunare responsible for making sure that the lock is initialized. 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun 88*4882a593SmuzhiyunRate Estimator: 89*4882a593Smuzhiyun--------------- 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun0) Prepare an estimator attribute. Most likely this would be in user 92*4882a593Smuzhiyun space. The value of this TLV should contain a tc_estimator structure. 93*4882a593Smuzhiyun As usual, such a TLV needs to be 32 bit aligned and therefore the 94*4882a593Smuzhiyun length needs to be appropriately set, etc. The estimator interval 95*4882a593Smuzhiyun and ewma log need to be converted to the appropriate values. 96*4882a593Smuzhiyun tc_estimator.c::tc_setup_estimator() is advisable to be used as the 97*4882a593Smuzhiyun conversion routine. It does a few clever things. It takes a time 98*4882a593Smuzhiyun interval in microsecs, a time constant also in microsecs and a struct 99*4882a593Smuzhiyun tc_estimator to be populated. The returned tc_estimator can be 100*4882a593Smuzhiyun transported to the kernel. Transfer such a structure in a TLV of type 101*4882a593Smuzhiyun TCA_RATE to your code in the kernel. 102*4882a593Smuzhiyun 103*4882a593SmuzhiyunIn the kernel when setting up: 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun1) make sure you have basic stats and rate stats setup first. 106*4882a593Smuzhiyun2) make sure you have initialized stats lock that is used to setup such 107*4882a593Smuzhiyun stats. 108*4882a593Smuzhiyun3) Now initialize a new estimator:: 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun int ret = gen_new_estimator(my_basicstats,my_rate_est_stats, 111*4882a593Smuzhiyun mystats_lock, attr_with_tcestimator_struct); 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun if ret == 0 114*4882a593Smuzhiyun success 115*4882a593Smuzhiyun else 116*4882a593Smuzhiyun failed 117*4882a593Smuzhiyun 118*4882a593SmuzhiyunFrom now on, every time you dump my_rate_est_stats it will contain 119*4882a593Smuzhiyunup-to-date info. 120*4882a593Smuzhiyun 121*4882a593SmuzhiyunOnce you are done, call gen_kill_estimator(my_basicstats, 122*4882a593Smuzhiyunmy_rate_est_stats) Make sure that my_basicstats and my_rate_est_stats 123*4882a593Smuzhiyunare still valid (i.e still exist) at the time of making this call. 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun 126*4882a593SmuzhiyunAuthors: 127*4882a593Smuzhiyun-------- 128*4882a593Smuzhiyun- Thomas Graf <tgraf@suug.ch> 129*4882a593Smuzhiyun- Jamal Hadi Salim <hadi@cyberus.ca> 130