mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
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 <petrm@nvidia.com> Signed-off-by: Petr Machata <petrm@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a207eab103
commit
f4676ea74b
@ -95,8 +95,14 @@ struct nh_res_table {
|
||||
struct nh_res_bucket nh_buckets[] __counted_by(num_nh_buckets);
|
||||
};
|
||||
|
||||
struct nh_grp_entry_stats {
|
||||
u64_stats_t packets;
|
||||
struct u64_stats_sync syncp;
|
||||
};
|
||||
|
||||
struct nh_grp_entry {
|
||||
struct nexthop *nh;
|
||||
struct nh_grp_entry_stats __percpu *stats;
|
||||
u8 weight;
|
||||
|
||||
union {
|
||||
|
@ -480,6 +480,7 @@ static void nexthop_free_group(struct nexthop *nh)
|
||||
struct nh_grp_entry *nhge = &nhg->nh_entries[i];
|
||||
|
||||
WARN_ON(!list_empty(&nhge->nh_list));
|
||||
free_percpu(nhge->stats);
|
||||
nexthop_put(nhge->nh);
|
||||
}
|
||||
|
||||
@ -660,6 +661,16 @@ nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static void nh_grp_entry_stats_inc(struct nh_grp_entry *nhge)
|
||||
{
|
||||
struct nh_grp_entry_stats *cpu_stats;
|
||||
|
||||
cpu_stats = this_cpu_ptr(nhge->stats);
|
||||
u64_stats_update_begin(&cpu_stats->syncp);
|
||||
u64_stats_inc(&cpu_stats->packets);
|
||||
u64_stats_update_end(&cpu_stats->syncp);
|
||||
}
|
||||
|
||||
static int nla_put_nh_group(struct sk_buff *skb, struct nh_group *nhg)
|
||||
{
|
||||
struct nexthop_grp *p;
|
||||
@ -1182,6 +1193,7 @@ static struct nexthop *nexthop_select_path_fdb(struct nh_group *nhg, int hash)
|
||||
if (hash > atomic_read(&nhge->hthr.upper_bound))
|
||||
continue;
|
||||
|
||||
nh_grp_entry_stats_inc(nhge);
|
||||
return nhge->nh;
|
||||
}
|
||||
|
||||
@ -1191,7 +1203,7 @@ static struct nexthop *nexthop_select_path_fdb(struct nh_group *nhg, int hash)
|
||||
|
||||
static struct nexthop *nexthop_select_path_hthr(struct nh_group *nhg, int hash)
|
||||
{
|
||||
struct nexthop *rc = NULL;
|
||||
struct nh_grp_entry *nhge0 = NULL;
|
||||
int i;
|
||||
|
||||
if (nhg->fdb_nh)
|
||||
@ -1206,16 +1218,20 @@ static struct nexthop *nexthop_select_path_hthr(struct nh_group *nhg, int hash)
|
||||
if (!nexthop_is_good_nh(nhge->nh))
|
||||
continue;
|
||||
|
||||
if (!rc)
|
||||
rc = nhge->nh;
|
||||
if (!nhge0)
|
||||
nhge0 = nhge;
|
||||
|
||||
if (hash > atomic_read(&nhge->hthr.upper_bound))
|
||||
continue;
|
||||
|
||||
nh_grp_entry_stats_inc(nhge);
|
||||
return nhge->nh;
|
||||
}
|
||||
|
||||
return rc ? : nhg->nh_entries[0].nh;
|
||||
if (!nhge0)
|
||||
nhge0 = &nhg->nh_entries[0];
|
||||
nh_grp_entry_stats_inc(nhge0);
|
||||
return nhge0->nh;
|
||||
}
|
||||
|
||||
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)
|
||||
bucket = &res_table->nh_buckets[bucket_index];
|
||||
nh_res_bucket_set_busy(bucket);
|
||||
nhge = rcu_dereference(bucket->nh_entry);
|
||||
nh_grp_entry_stats_inc(nhge);
|
||||
return nhge->nh;
|
||||
}
|
||||
|
||||
@ -1804,6 +1821,7 @@ static void remove_nh_grp_entry(struct net *net, struct nh_grp_entry *nhge,
|
||||
newg->has_v4 = true;
|
||||
|
||||
list_del(&nhges[i].nh_list);
|
||||
new_nhges[j].stats = nhges[i].stats;
|
||||
new_nhges[j].nh_parent = nhges[i].nh_parent;
|
||||
new_nhges[j].nh = nhges[i].nh;
|
||||
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,
|
||||
rcu_assign_pointer(nhp->nh_grp, newg);
|
||||
|
||||
list_del(&nhge->nh_list);
|
||||
free_percpu(nhge->stats);
|
||||
nexthop_put(nhge->nh);
|
||||
|
||||
/* Removal of a NH from a resilient group is notified through
|
||||
@ -2483,6 +2502,13 @@ static struct nexthop *nexthop_create_group(struct net *net,
|
||||
if (nhi->family == AF_INET)
|
||||
nhg->has_v4 = true;
|
||||
|
||||
nhg->nh_entries[i].stats =
|
||||
netdev_alloc_pcpu_stats(struct nh_grp_entry_stats);
|
||||
if (!nhg->nh_entries[i].stats) {
|
||||
err = -ENOMEM;
|
||||
nexthop_put(nhe);
|
||||
goto out_no_nh;
|
||||
}
|
||||
nhg->nh_entries[i].nh = nhe;
|
||||
nhg->nh_entries[i].weight = entry[i].weight + 1;
|
||||
list_add(&nhg->nh_entries[i].nh_list, &nhe->grp_list);
|
||||
@ -2522,6 +2548,7 @@ static struct nexthop *nexthop_create_group(struct net *net,
|
||||
out_no_nh:
|
||||
for (i--; i >= 0; --i) {
|
||||
list_del(&nhg->nh_entries[i].nh_list);
|
||||
free_percpu(nhg->nh_entries[i].stats);
|
||||
nexthop_put(nhg->nh_entries[i].nh);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user