On Wed, 2020-09-30 at 09:44 -0700, Jakub Kicinski wrote:

> I started with a get_policy() callback, but I didn't like it much.
> Static data is much more pleasant for a client of the API IMHO.

Yeah, true.

> What do you think about "ops light"? Insufficiently flexible?

TBH, I'm not really sure how you'd do it?

Admittedly, it _would_ be nice to reduce struct genl_ops further, I
could imagine, assuming that doit is far more common than anything else,
perhaps something like

diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index b9eb92f3fe86..a5abab50673c 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -125,23 +125,34 @@ genl_dumpit_info(struct netlink_callback *cb)
        return cb->data;
 }
 
+/**
+ * struct genl_ops_ext - full generic netlink operations
+ * @start: start callback for dumps
+ * @dumpit: callback for dumpers
+ * @done: completion callback for dumps
+ * @policy: policy if different from the family policy
+ * @maxattr: max attr for the policy
+ */
+struct genl_ops_ext {
+       int (*start)(struct netlink_callback *cb);
+       int (*dumpit)(struct sk_buff *skb,
+                     struct netlink_callback *cb);
+       int (*done)(struct netlink_callback *cb);
+       const struct nla_policy *policy;
+       unsigned int maxattr;
+};
+
 /**
  * struct genl_ops - generic netlink operations
  * @cmd: command identifier
  * @internal_flags: flags used by the family
  * @flags: flags
  * @doit: standard command callback
- * @start: start callback for dumps
- * @dumpit: callback for dumpers
- * @done: completion callback for dumps
  */
 struct genl_ops {
        int                    (*doit)(struct sk_buff *skb,
                                       struct genl_info *info);
-       int                    (*start)(struct netlink_callback *cb);
-       int                    (*dumpit)(struct sk_buff *skb,
-                                        struct netlink_callback *cb);
-       int                    (*done)(struct netlink_callback *cb);
+       struct genl_ops_ext     *extops;
        u8                      cmd;
        u8                      internal_flags;
        u8                      flags;

... 

or perhaps even

diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index b9eb92f3fe86..9be3fc051400 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -125,29 +125,45 @@ genl_dumpit_info(struct netlink_callback *cb)
        return cb->data;
 }
 
+/**
+ * struct genl_ops_ext - full generic netlink operations
+ * @start: start callback for dumps
+ * @dumpit: callback for dumpers
+ * @done: completion callback for dumps
+ * @doit: standard command callback
+ * @policy: policy if different from the family policy
+ * @maxattr: max attr for the policy
+ */
+struct genl_ops_ext {
+       int (*start)(struct netlink_callback *cb);
+       int (*dumpit)(struct sk_buff *skb, struct netlink_callback *cb);
+       int (*done)(struct netlink_callback *cb);
+       int (*doit)(struct sk_buff *skb, struct genl_info *info);
+       const struct nla_policy *policy;
+       unsigned int maxattr;
+};
+
 /**
  * struct genl_ops - generic netlink operations
  * @cmd: command identifier
  * @internal_flags: flags used by the family
  * @flags: flags
  * @doit: standard command callback
- * @start: start callback for dumps
- * @dumpit: callback for dumpers
- * @done: completion callback for dumps
+ * @extops: extended ops if needed, must use GENL_EXTOPS()
  */
 struct genl_ops {
-       int                    (*doit)(struct sk_buff *skb,
-                                      struct genl_info *info);
-       int                    (*start)(struct netlink_callback *cb);
-       int                    (*dumpit)(struct sk_buff *skb,
-                                        struct netlink_callback *cb);
-       int                    (*done)(struct netlink_callback *cb);
+       union {
+               int (*doit)(struct sk_buff *skb, struct genl_info *info);
+               struct genl_ops_ext *extops;
+       };
        u8                      cmd;
        u8                      internal_flags;
        u8                      flags;
        u8                      validate;
 };
 
+#define GENL_EXT_OPS(ptr) ((struct genl_ops_ext *)((uintptr_t)(ptr) | 1))
+
 int genl_register_family(struct genl_family *family);
 int genl_unregister_family(const struct genl_family *family);
 void genl_notify(const struct genl_family *family, struct sk_buff *skb,




But both sort of feel awkward, you have to declare another structure,
and link it manually to the right place?

There isn't really a _good_ way to express such a thing easily in C?

johannes

Reply via email to