net: nexthop: Add NHA_OP_FLAGS
authorPetr Machata <petrm@nvidia.com>
Wed, 6 Mar 2024 12:49:16 +0000 (13:49 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Mar 2024 10:35:46 +0000 (10:35 +0000)
In order to add per-nexthop statistics, but still not increase netlink
message size for consumers that do not care about them, there needs to be a
toggle through which the user indicates their desire to get the statistics.
To that end, add a new attribute, NHA_OP_FLAGS. The idea is to be able to
use the attribute for carrying of arbitrary operation-specific flags, i.e.
not make it specific for get / dump.

Add the new attribute to get and dump policies, but do not actually allow
any flags yet -- those will come later as the flags themselves are defined.
Add the necessary parsing code.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/nexthop.h
net/ipv4/nexthop.c

index d8ffa8c9ca78492ec1f18c2634f20eb8f79b6ee7..086444e2946c82b5ee6248e8812b844078ddaad8 100644 (file)
@@ -60,6 +60,9 @@ enum {
        /* nested; nexthop bucket attributes */
        NHA_RES_BUCKET,
 
+       /* u32; operation-specific flags */
+       NHA_OP_FLAGS,
+
        __NHA_MAX,
 };
 
index bcd4df2f1cad4943d9d4edbf391a5deed47c9936..576981f4ca498f6dc7c8d95e757e99ed337a0a8f 100644 (file)
@@ -41,6 +41,7 @@ static const struct nla_policy rtm_nh_policy_new[] = {
 
 static const struct nla_policy rtm_nh_policy_get[] = {
        [NHA_ID]                = { .type = NLA_U32 },
+       [NHA_OP_FLAGS]          = NLA_POLICY_MASK(NLA_U32, 0),
 };
 
 static const struct nla_policy rtm_nh_policy_del[] = {
@@ -52,6 +53,7 @@ static const struct nla_policy rtm_nh_policy_dump[] = {
        [NHA_GROUPS]            = { .type = NLA_FLAG },
        [NHA_MASTER]            = { .type = NLA_U32 },
        [NHA_FDB]               = { .type = NLA_FLAG },
+       [NHA_OP_FLAGS]          = NLA_POLICY_MASK(NLA_U32, 0),
 };
 
 static const struct nla_policy rtm_nh_res_policy_new[] = {
@@ -2971,7 +2973,7 @@ static int rtm_new_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
 }
 
 static int nh_valid_get_del_req(const struct nlmsghdr *nlh,
-                               struct nlattr **tb, u32 *id,
+                               struct nlattr **tb, u32 *id, u32 *op_flags,
                                struct netlink_ext_ack *extack)
 {
        struct nhmsg *nhm = nlmsg_data(nlh);
@@ -2992,6 +2994,11 @@ static int nh_valid_get_del_req(const struct nlmsghdr *nlh,
                return -EINVAL;
        }
 
+       if (tb[NHA_OP_FLAGS])
+               *op_flags = nla_get_u32(tb[NHA_OP_FLAGS]);
+       else
+               *op_flags = 0;
+
        return 0;
 }
 
@@ -3007,6 +3014,7 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
                .portid = NETLINK_CB(skb).portid,
        };
        struct nexthop *nh;
+       u32 op_flags;
        int err;
        u32 id;
 
@@ -3015,7 +3023,7 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (err < 0)
                return err;
 
-       err = nh_valid_get_del_req(nlh, tb, &id, extack);
+       err = nh_valid_get_del_req(nlh, tb, &id, &op_flags, extack);
        if (err)
                return err;
 
@@ -3036,6 +3044,7 @@ static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
        struct nlattr *tb[NHA_MAX + 1];
        struct sk_buff *skb = NULL;
        struct nexthop *nh;
+       u32 op_flags;
        int err;
        u32 id;
 
@@ -3044,7 +3053,7 @@ static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
        if (err < 0)
                return err;
 
-       err = nh_valid_get_del_req(nlh, tb, &id, extack);
+       err = nh_valid_get_del_req(nlh, tb, &id, &op_flags, extack);
        if (err)
                return err;
 
@@ -3080,6 +3089,7 @@ struct nh_dump_filter {
        bool group_filter;
        bool fdb_filter;
        u32 res_bucket_nh_id;
+       u32 op_flags;
 };
 
 static bool nh_dump_filtered(struct nexthop *nh,
@@ -3151,6 +3161,11 @@ static int __nh_valid_dump_req(const struct nlmsghdr *nlh, struct nlattr **tb,
                return -EINVAL;
        }
 
+       if (tb[NHA_OP_FLAGS])
+               filter->op_flags = nla_get_u32(tb[NHA_OP_FLAGS]);
+       else
+               filter->op_flags = 0;
+
        return 0;
 }
 
@@ -3474,6 +3489,7 @@ static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
                                   struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[NHA_MAX + 1];
+       u32 op_flags;
        int err;
 
        err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
@@ -3481,7 +3497,7 @@ static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
        if (err < 0)
                return err;
 
-       err = nh_valid_get_del_req(nlh, tb, id, extack);
+       err = nh_valid_get_del_req(nlh, tb, id, &op_flags, extack);
        if (err)
                return err;