On 18.10.2020 15:48, Vladimir Oltean wrote: > On Sun, Oct 18, 2020 at 03:09:32PM +0200, Heiner Kallweit wrote: >> On 18.10.2020 14:16, Vladimir Oltean wrote: >>> On Sun, Oct 18, 2020 at 02:02:46PM +0200, Heiner Kallweit wrote: >>>> Wouldn't a simple unsigned long (like in struct net_device_stats) be >>>> sufficient here? This would make handling the counter much simpler. >>>> And as far as I understand we talk about a packet counter that is >>>> touched in certain scenarios only. >>> >>> I don't understand, in what sense 'sufficient'? This counter is exported >>> to ethtool which works with u64 values, how would an unsigned long, >>> which is u32 on 32-bit systems, help? >>> >> Sufficient for me means that it's unlikely that a 32 bit counter will >> overflow. Many drivers use the 32 bit counters (on a 32bit system) in >> net_device_stats for infrequent events like rx/tx errors, and 64bit >> counters only for things like rx/tx bytes, which are more likely to >> overflow. > > 2^32 = 4,294,967,296 = 4 billion packets > Considering that every packet that needs TX timestamping must be > reallocated, protocols such as IEEE 802.1AS will trigger 5 reallocs per > second. So time synchronization alone (background traffic, by all > accounts) will make this counter overflow in 27 years. > Every packet flooded or multicast by the bridge will also trigger > reallocs. In this case it is not difficult to imagine that overflows > might occur sooner. > > Even if the above wasn't true. What becomes easier when I make the > counter an unsigned long? I need to make arch-dependent casts between an > unsigned long an an u64 when I expose the counter to ethtool, and there > it ends up being u64 too, doesn't it? >
Access to unsigned long should be atomic, so you could avoid the following and access the counter directly (like other drivers do it with the net_device_stats members). On a side note, because I'm also just dealing with it: this_cpu_ptr() is safe only if preemption is disabled. Is this the case here? Else there's get_cpu_ptr/put_cpu_ptr. Also, if irq's aren't disabled there might be a need to use u64_stats_update_begin_irqsave() et al. See: 2695578b896a ("net: usbnet: fix potential deadlock on 32bit hosts") But I don't know dsa good enough to say whether this is applicable here. + e = this_cpu_ptr(p->extra_stats); + u64_stats_update_begin(&e->syncp); + e->tx_reallocs++; + u64_stats_update_end(&e->syncp); + e = per_cpu_ptr(p->extra_stats, i); + do { + start = u64_stats_fetch_begin_irq(&e->syncp); + tx_reallocs = e->tx_reallocs; + } while (u64_stats_fetch_retry_irq(&e->syncp, start));