Skip to content

Commit 0b05315

Browse files
committed
net: nexthop: Expose nexthop group stats to user space
JIRA: https://issues.redhat.com/browse/RHEL-59118 commit 95fedd7 Author: Ido Schimmel <idosch@nvidia.com> Date: Wed Mar 6 13:49:18 2024 +0100 net: nexthop: Expose nexthop group stats to user space Add netlink support for reading NH group stats. This data is only for statistics of the traffic in the SW datapath. HW nexthop group statistics will be added in the following patches. Emission of the stats is keyed to a new op_stats flag to avoid cluttering the netlink message with stats if the user doesn't need them: NHA_OP_FLAG_DUMP_STATS. 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> Signed-off-by: Ivan Vecera <ivecera@redhat.com>
1 parent b61aa88 commit 0b05315

File tree

2 files changed

+117
-8
lines changed

2 files changed

+117
-8
lines changed

include/uapi/linux/nexthop.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ enum {
3030

3131
#define NEXTHOP_GRP_TYPE_MAX (__NEXTHOP_GRP_TYPE_MAX - 1)
3232

33+
#define NHA_OP_FLAG_DUMP_STATS BIT(0)
34+
3335
enum {
3436
NHA_UNSPEC,
3537
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */
@@ -63,6 +65,9 @@ enum {
6365
/* u32; operation-specific flags */
6466
NHA_OP_FLAGS,
6567

68+
/* nested; nexthop group stats */
69+
NHA_GROUP_STATS,
70+
6671
__NHA_MAX,
6772
};
6873

@@ -104,4 +109,29 @@ enum {
104109

105110
#define NHA_RES_BUCKET_MAX (__NHA_RES_BUCKET_MAX - 1)
106111

112+
enum {
113+
NHA_GROUP_STATS_UNSPEC,
114+
115+
/* nested; nexthop group entry stats */
116+
NHA_GROUP_STATS_ENTRY,
117+
118+
__NHA_GROUP_STATS_MAX,
119+
};
120+
121+
#define NHA_GROUP_STATS_MAX (__NHA_GROUP_STATS_MAX - 1)
122+
123+
enum {
124+
NHA_GROUP_STATS_ENTRY_UNSPEC,
125+
126+
/* u32; nexthop id of the nexthop group entry */
127+
NHA_GROUP_STATS_ENTRY_ID,
128+
129+
/* uint; number of packets forwarded via the nexthop group entry */
130+
NHA_GROUP_STATS_ENTRY_PACKETS,
131+
132+
__NHA_GROUP_STATS_ENTRY_MAX,
133+
};
134+
135+
#define NHA_GROUP_STATS_ENTRY_MAX (__NHA_GROUP_STATS_ENTRY_MAX - 1)
136+
107137
#endif

net/ipv4/nexthop.c

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ static void remove_nexthop(struct net *net, struct nexthop *nh,
2626
#define NH_DEV_HASHBITS 8
2727
#define NH_DEV_HASHSIZE (1U << NH_DEV_HASHBITS)
2828

29+
#define NHA_OP_FLAGS_DUMP_ALL (NHA_OP_FLAG_DUMP_STATS)
30+
2931
static const struct nla_policy rtm_nh_policy_new[] = {
3032
[NHA_ID] = { .type = NLA_U32 },
3133
[NHA_GROUP] = { .type = NLA_BINARY },
@@ -41,7 +43,8 @@ static const struct nla_policy rtm_nh_policy_new[] = {
4143

4244
static const struct nla_policy rtm_nh_policy_get[] = {
4345
[NHA_ID] = { .type = NLA_U32 },
44-
[NHA_OP_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0),
46+
[NHA_OP_FLAGS] = NLA_POLICY_MASK(NLA_U32,
47+
NHA_OP_FLAGS_DUMP_ALL),
4548
};
4649

4750
static const struct nla_policy rtm_nh_policy_del[] = {
@@ -53,7 +56,8 @@ static const struct nla_policy rtm_nh_policy_dump[] = {
5356
[NHA_GROUPS] = { .type = NLA_FLAG },
5457
[NHA_MASTER] = { .type = NLA_U32 },
5558
[NHA_FDB] = { .type = NLA_FLAG },
56-
[NHA_OP_FLAGS] = NLA_POLICY_MASK(NLA_U32, 0),
59+
[NHA_OP_FLAGS] = NLA_POLICY_MASK(NLA_U32,
60+
NHA_OP_FLAGS_DUMP_ALL),
5761
};
5862

5963
static const struct nla_policy rtm_nh_res_policy_new[] = {
@@ -671,8 +675,78 @@ static void nh_grp_entry_stats_inc(struct nh_grp_entry *nhge)
671675
u64_stats_update_end(&cpu_stats->syncp);
672676
}
673677

674-
static int nla_put_nh_group(struct sk_buff *skb, struct nh_group *nhg)
678+
static void nh_grp_entry_stats_read(struct nh_grp_entry *nhge,
679+
u64 *ret_packets)
680+
{
681+
int i;
682+
683+
*ret_packets = 0;
684+
685+
for_each_possible_cpu(i) {
686+
struct nh_grp_entry_stats *cpu_stats;
687+
unsigned int start;
688+
u64 packets;
689+
690+
cpu_stats = per_cpu_ptr(nhge->stats, i);
691+
do {
692+
start = u64_stats_fetch_begin(&cpu_stats->syncp);
693+
packets = u64_stats_read(&cpu_stats->packets);
694+
} while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
695+
696+
*ret_packets += packets;
697+
}
698+
}
699+
700+
static int nla_put_nh_group_stats_entry(struct sk_buff *skb,
701+
struct nh_grp_entry *nhge)
702+
{
703+
struct nlattr *nest;
704+
u64 packets;
705+
706+
nh_grp_entry_stats_read(nhge, &packets);
707+
708+
nest = nla_nest_start(skb, NHA_GROUP_STATS_ENTRY);
709+
if (!nest)
710+
return -EMSGSIZE;
711+
712+
if (nla_put_u32(skb, NHA_GROUP_STATS_ENTRY_ID, nhge->nh->id) ||
713+
nla_put_uint(skb, NHA_GROUP_STATS_ENTRY_PACKETS, packets))
714+
goto nla_put_failure;
715+
716+
nla_nest_end(skb, nest);
717+
return 0;
718+
719+
nla_put_failure:
720+
nla_nest_cancel(skb, nest);
721+
return -EMSGSIZE;
722+
}
723+
724+
static int nla_put_nh_group_stats(struct sk_buff *skb, struct nexthop *nh)
675725
{
726+
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
727+
struct nlattr *nest;
728+
int i;
729+
730+
nest = nla_nest_start(skb, NHA_GROUP_STATS);
731+
if (!nest)
732+
return -EMSGSIZE;
733+
734+
for (i = 0; i < nhg->num_nh; i++)
735+
if (nla_put_nh_group_stats_entry(skb, &nhg->nh_entries[i]))
736+
goto cancel_out;
737+
738+
nla_nest_end(skb, nest);
739+
return 0;
740+
741+
cancel_out:
742+
nla_nest_cancel(skb, nest);
743+
return -EMSGSIZE;
744+
}
745+
746+
static int nla_put_nh_group(struct sk_buff *skb, struct nexthop *nh,
747+
u32 op_flags)
748+
{
749+
struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
676750
struct nexthop_grp *p;
677751
size_t len = nhg->num_nh * sizeof(*p);
678752
struct nlattr *nla;
@@ -701,14 +775,19 @@ static int nla_put_nh_group(struct sk_buff *skb, struct nh_group *nhg)
701775
if (nhg->resilient && nla_put_nh_group_res(skb, nhg))
702776
goto nla_put_failure;
703777

778+
if (op_flags & NHA_OP_FLAG_DUMP_STATS &&
779+
nla_put_nh_group_stats(skb, nh))
780+
goto nla_put_failure;
781+
704782
return 0;
705783

706784
nla_put_failure:
707785
return -EMSGSIZE;
708786
}
709787

710788
static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
711-
int event, u32 portid, u32 seq, unsigned int nlflags)
789+
int event, u32 portid, u32 seq, unsigned int nlflags,
790+
u32 op_flags)
712791
{
713792
struct fib6_nh *fib6_nh;
714793
struct fib_nh *fib_nh;
@@ -735,7 +814,7 @@ static int nh_fill_node(struct sk_buff *skb, struct nexthop *nh,
735814

736815
if (nhg->fdb_nh && nla_put_flag(skb, NHA_FDB))
737816
goto nla_put_failure;
738-
if (nla_put_nh_group(skb, nhg))
817+
if (nla_put_nh_group(skb, nh, op_flags))
739818
goto nla_put_failure;
740819
goto out;
741820
}
@@ -866,7 +945,7 @@ static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info)
866945
if (!skb)
867946
goto errout;
868947

869-
err = nh_fill_node(skb, nh, event, info->portid, seq, nlflags);
948+
err = nh_fill_node(skb, nh, event, info->portid, seq, nlflags, 0);
870949
if (err < 0) {
871950
/* -EMSGSIZE implies BUG in nh_nlmsg_size() */
872951
WARN_ON(err == -EMSGSIZE);
@@ -3093,7 +3172,7 @@ static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
30933172
goto errout_free;
30943173

30953174
err = nh_fill_node(skb, nh, RTM_NEWNEXTHOP, NETLINK_CB(in_skb).portid,
3096-
nlh->nlmsg_seq, 0);
3175+
nlh->nlmsg_seq, 0, op_flags);
30973176
if (err < 0) {
30983177
WARN_ON(err == -EMSGSIZE);
30993178
goto errout_free;
@@ -3264,7 +3343,7 @@ static int rtm_dump_nexthop_cb(struct sk_buff *skb, struct netlink_callback *cb,
32643343

32653344
return nh_fill_node(skb, nh, RTM_NEWNEXTHOP,
32663345
NETLINK_CB(cb->skb).portid,
3267-
cb->nlh->nlmsg_seq, NLM_F_MULTI);
3346+
cb->nlh->nlmsg_seq, NLM_F_MULTI, filter->op_flags);
32683347
}
32693348

32703349
/* rtnl */

0 commit comments

Comments
 (0)