net/core/gen_stats.c

Source file repositories/reference/linux-study-clean/net/core/gen_stats.c

File Facts

System
Linux kernel
Corpus path
net/core/gen_stats.c
Extension
.c
Size
13674 bytes
Lines
485
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

for_each_possible_cpu(i) {
			const struct gnet_stats_basic_sync *bcpu = per_cpu_ptr(cpu, i);
			u64 bytes, packets;

			do {
				start = u64_stats_fetch_begin(&bcpu->syncp);
				bytes = u64_stats_read(&bcpu->bytes);
				packets = u64_stats_read(&bcpu->packets);
			} while (u64_stats_fetch_retry(&bcpu->syncp, start));

			t_bytes += bytes;
			t_packets += packets;
		}
		*ret_bytes = t_bytes;
		*ret_packets = t_packets;
		return;
	}
	do {
		if (running)
			start = u64_stats_fetch_begin(&b->syncp);
		*ret_bytes = u64_stats_read(&b->bytes);
		*ret_packets = u64_stats_read(&b->packets);
	} while (running && u64_stats_fetch_retry(&b->syncp, start));
}

static int
___gnet_stats_copy_basic(struct gnet_dump *d,
			 const struct gnet_stats_basic_sync __percpu *cpu,
			 const struct gnet_stats_basic_sync *b,
			 int type, bool running)
{
	u64 bstats_bytes, bstats_packets;

	gnet_stats_read_basic(&bstats_bytes, &bstats_packets, cpu, b, running);

	if (d->compat_tc_stats && type == TCA_STATS_BASIC) {
		d->tc_stats.bytes = bstats_bytes;
		d->tc_stats.packets = bstats_packets;
	}

	if (d->tail) {
		struct gnet_stats_basic sb;
		int res;

		memset(&sb, 0, sizeof(sb));
		sb.bytes = bstats_bytes;
		sb.packets = bstats_packets;
		res = gnet_stats_copy(d, type, &sb, sizeof(sb), TCA_STATS_PAD);
		if (res < 0 || sb.packets == bstats_packets)
			return res;
		/* emit 64bit stats only if needed */
		return gnet_stats_copy(d, TCA_STATS_PKT64, &bstats_packets,
				       sizeof(bstats_packets), TCA_STATS_PAD);
	}
	return 0;
}

/**
 * gnet_stats_copy_basic - copy basic statistics into statistic TLV
 * @d: dumping handle
 * @cpu: copy statistic per cpu
 * @b: basic statistics
 * @running: true if @b represents a running qdisc, thus @b's
 *           internal values might change during basic reads.
 *           Only used if @cpu is NULL
 *
 * Context: task; must not be run from IRQ or BH contexts
 *
 * Appends the basic statistics to the top level TLV created by
 * gnet_stats_start_copy().
 *
 * Returns 0 on success or -1 with the statistic lock released
 * if the room in the socket buffer was not sufficient.
 */
int
gnet_stats_copy_basic(struct gnet_dump *d,
		      const struct gnet_stats_basic_sync __percpu *cpu,
		      const struct gnet_stats_basic_sync *b,
		      bool running)
{
	return ___gnet_stats_copy_basic(d, cpu, b, TCA_STATS_BASIC, running);
}
EXPORT_SYMBOL(gnet_stats_copy_basic);

/**
 * gnet_stats_copy_basic_hw - copy basic hw statistics into statistic TLV
 * @d: dumping handle
 * @cpu: copy statistic per cpu
 * @b: basic statistics
 * @running: true if @b represents a running qdisc, thus @b's

Annotation

Implementation Notes