Skip to content

Commit f4676ea

Browse files
idoschdavem330
authored andcommitted
net: nexthop: Add nexthop group entry stats
Add nexthop group entry stats to count the number of packets forwarded via each nexthop in the group. The stats will be exposed to user space for better data path observability in the next patch. The per-CPU stats pointer is placed at the beginning of 'struct nh_grp_entry', so that all the fields accessed for the data path reside on the same cache line: struct nh_grp_entry { struct nexthop * nh; /* 0 8 */ struct nh_grp_entry_stats * stats; /* 8 8 */ u8 weight; /* 16 1 */ /* XXX 7 bytes hole, try to pack */ union { struct { atomic_t upper_bound; /* 24 4 */ } hthr; /* 24 4 */ struct { struct list_head uw_nh_entry; /* 24 16 */ u16 count_buckets; /* 40 2 */ u16 wants_buckets; /* 42 2 */ } res; /* 24 24 */ }; /* 24 24 */ struct list_head nh_list; /* 48 16 */ /* --- cacheline 1 boundary (64 bytes) --- */ struct nexthop * nh_parent; /* 64 8 */ /* size: 72, cachelines: 2, members: 6 */ /* sum members: 65, holes: 1, sum holes: 7 */ /* last cacheline: 8 bytes */ }; Co-developed-by: Petr Machata <[email protected]> Signed-off-by: Petr Machata <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a207eab commit f4676ea

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

include/net/nexthop.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,14 @@ struct nh_res_table {
9595
struct nh_res_bucket nh_buckets[] __counted_by(num_nh_buckets);
9696
};
9797

98+
struct nh_grp_entry_stats {
99+
u64_stats_t packets;
100+
struct u64_stats_sync syncp;
101+
};
102+
98103
struct nh_grp_entry {
99104
struct nexthop *nh;
105+
struct nh_grp_entry_stats __percpu *stats;
100106
u8 weight;
101107

102108
union {

net/ipv4/nexthop.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ static void nexthop_free_group(struct nexthop *nh)
480480
struct nh_grp_entry *nhge = &nhg->nh_entries[i];
481481

482482
WARN_ON(!list_empty(&nhge->nh_list));
483+
free_percpu(nhge->stats);
483484
nexthop_put(nhge->nh);
484485
}
485486

@@ -660,6 +661,16 @@ static int nla_put_nh_group_res(struct sk_buff *skb, struct nh_group *nhg)
660661
return -EMSGSIZE;
661662
}
662663

664+
static void nh_grp_entry_stats_inc(struct nh_grp_entry *nhge)
665+
{
666+
struct nh_grp_entry_stats *cpu_stats;
667+
668+
cpu_stats = this_cpu_ptr(nhge->stats);
669+
u64_stats_update_begin(&cpu_stats->syncp);
670+
u64_stats_inc(&cpu_stats->packets);
671+
u64_stats_update_end(&cpu_stats->syncp);
672+
}
673+
663674
static int nla_put_nh_group(struct sk_buff *skb, struct nh_group *nhg)
664675
{
665676
struct nexthop_grp *p;
@@ -1182,6 +1193,7 @@ static struct nexthop *nexthop_select_path_fdb(struct nh_group *nhg, int hash)
11821193
if (hash > atomic_read(&nhge->hthr.upper_bound))
11831194
continue;
11841195

1196+
nh_grp_entry_stats_inc(nhge);
11851197
return nhge->nh;
11861198
}
11871199

@@ -1191,7 +1203,7 @@ static struct nexthop *nexthop_select_path_fdb(struct nh_group *nhg, int hash)
11911203

11921204
static struct nexthop *nexthop_select_path_hthr(struct nh_group *nhg, int hash)
11931205
{
1194-
struct nexthop *rc = NULL;
1206+
struct nh_grp_entry *nhge0 = NULL;
11951207
int i;
11961208

11971209
if (nhg->fdb_nh)
@@ -1206,16 +1218,20 @@ static struct nexthop *nexthop_select_path_hthr(struct nh_group *nhg, int hash)
12061218
if (!nexthop_is_good_nh(nhge->nh))
12071219
continue;
12081220

1209-
if (!rc)
1210-
rc = nhge->nh;
1221+
if (!nhge0)
1222+
nhge0 = nhge;
12111223

12121224
if (hash > atomic_read(&nhge->hthr.upper_bound))
12131225
continue;
12141226

1227+
nh_grp_entry_stats_inc(nhge);
12151228
return nhge->nh;
12161229
}
12171230

1218-
return rc ? : nhg->nh_entries[0].nh;
1231+
if (!nhge0)
1232+
nhge0 = &nhg->nh_entries[0];
1233+
nh_grp_entry_stats_inc(nhge0);
1234+
return nhge0->nh;
12191235
}
12201236

12211237
static struct nexthop *nexthop_select_path_res(struct nh_group *nhg, int hash)
@@ -1231,6 +1247,7 @@ static struct nexthop *nexthop_select_path_res(struct nh_group *nhg, int hash)
12311247
bucket = &res_table->nh_buckets[bucket_index];
12321248
nh_res_bucket_set_busy(bucket);
12331249
nhge = rcu_dereference(bucket->nh_entry);
1250+
nh_grp_entry_stats_inc(nhge);
12341251
return nhge->nh;
12351252
}
12361253

@@ -1804,6 +1821,7 @@ static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge,
18041821
newg->has_v4 = true;
18051822

18061823
list_del(&nhges[i].nh_list);
1824+
new_nhges[j].stats = nhges[i].stats;
18071825
new_nhges[j].nh_parent = nhges[i].nh_parent;
18081826
new_nhges[j].nh = nhges[i].nh;
18091827
new_nhges[j].weight = nhges[i].weight;
@@ -1819,6 +1837,7 @@ static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge,
18191837
rcu_assign_pointer(nhp->nh_grp, newg);
18201838

18211839
list_del(&nhge->nh_list);
1840+
free_percpu(nhge->stats);
18221841
nexthop_put(nhge->nh);
18231842

18241843
/* Removal of a NH from a resilient group is notified through
@@ -2483,6 +2502,13 @@ static struct nexthop *nexthop_create_group(struct net *net,
24832502
if (nhi->family == AF_INET)
24842503
nhg->has_v4 = true;
24852504

2505+
nhg->nh_entries[i].stats =
2506+
netdev_alloc_pcpu_stats(struct nh_grp_entry_stats);
2507+
if (!nhg->nh_entries[i].stats) {
2508+
err = -ENOMEM;
2509+
nexthop_put(nhe);
2510+
goto out_no_nh;
2511+
}
24862512
nhg->nh_entries[i].nh = nhe;
24872513
nhg->nh_entries[i].weight = entry[i].weight + 1;
24882514
list_add(&nhg->nh_entries[i].nh_list, &nhe->grp_list);
@@ -2522,6 +2548,7 @@ static struct nexthop *nexthop_create_group(struct net *net,
25222548
out_no_nh:
25232549
for (i--; i >= 0; --i) {
25242550
list_del(&nhg->nh_entries[i].nh_list);
2551+
free_percpu(nhg->nh_entries[i].stats);
25252552
nexthop_put(nhg->nh_entries[i].nh);
25262553
}
25272554

0 commit comments

Comments
 (0)