new file mode 100644
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+
+name: ultraeth
+protocol: genetlink
+uapi-header: linux/ultraeth_nl.h
+
+doc: Ultra Ethernet driver genetlink operations
+
+attribute-sets:
+ -
+ name: context
+ attributes:
+ -
+ name: id
+ type: s32
+ checks:
+ min: 0
+ max: 255
+ -
+ name: contexts
+ attributes:
+ -
+ name: context
+ type: nest
+ nested-attributes: context
+ multi-attr: true
+
+operations:
+ name-prefix: ultraeth-cmd-
+ list:
+ -
+ name: context-get
+ doc: dump ultraeth context information
+ attribute-set: context
+ dump:
+ reply:
+ attributes: &all-context-attrs
+ - id
+ -
+ name: context-new
+ doc: add new ultraeth context
+ attribute-set: context
+ flags: [ admin-perm ]
+ do:
+ request:
+ attributes:
+ - id
+ -
+ name: context-del
+ doc: delete ultraeth context
+ attribute-set: context
+ flags: [ admin-perm ]
+ do:
+ request:
+ attributes:
+ - id
@@ -1,3 +1,3 @@
obj-$(CONFIG_ULTRAETH) += ultraeth.o
-ultraeth-objs := uet_main.o uet_context.o
+ultraeth-objs := uet_main.o uet_context.o uet_netlink.o
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
#include <net/ultraeth/uet_context.h>
+#include "uet_netlink.h"
#define MAX_CONTEXT_ID 256
static DECLARE_BITMAP(uet_context_ids, MAX_CONTEXT_ID);
@@ -147,3 +148,74 @@ void uet_context_destroy_all(void)
WARN_ON(!list_empty(&uet_context_list));
mutex_unlock(&uet_context_lock);
}
+
+static int __nl_ctx_fill_one(struct sk_buff *skb,
+ const struct uet_context *ctx,
+ int cmd, u32 flags, u32 seq, u32 portid)
+{
+ void *hdr;
+
+ hdr = genlmsg_put(skb, portid, seq, &ultraeth_nl_family, flags, cmd);
+ if (!hdr)
+ return -EMSGSIZE;
+
+ if (nla_put_s32(skb, ULTRAETH_A_CONTEXT_ID, ctx->id))
+ goto out_err;
+
+ genlmsg_end(skb, hdr);
+ return 0;
+
+out_err:
+ genlmsg_cancel(skb, hdr);
+ return -EMSGSIZE;
+}
+
+int ultraeth_nl_context_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx = 0, s_idx = cb->args[0], err;
+ struct uet_context *ctx;
+
+ mutex_lock(&uet_context_lock);
+ list_for_each_entry(ctx, &uet_context_list, list) {
+ if (idx < s_idx) {
+ idx++;
+ continue;
+ }
+ err = __nl_ctx_fill_one(skb, ctx, ULTRAETH_CMD_CONTEXT_GET,
+ NLM_F_MULTI, cb->nlh->nlmsg_seq,
+ NETLINK_CB(cb->skb).portid);
+ if (err)
+ break;
+ idx++;
+ }
+ cb->args[0] = idx;
+ mutex_unlock(&uet_context_lock);
+
+ return err ? err : skb->len;
+}
+
+int ultraeth_nl_context_new_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ int id = -1;
+
+ if (info->attrs[ULTRAETH_A_CONTEXT_ID])
+ id = nla_get_s32(info->attrs[ULTRAETH_A_CONTEXT_ID]);
+
+ return uet_context_create(id);
+}
+
+int ultraeth_nl_context_del_doit(struct sk_buff *skb, struct genl_info *info)
+{
+ bool destroyed = false;
+ int id;
+
+ if (!info->attrs[ULTRAETH_A_CONTEXT_ID]) {
+ NL_SET_ERR_MSG(info->extack, "UET context id must be specified");
+ return -EINVAL;
+ }
+
+ id = nla_get_s32(info->attrs[ULTRAETH_A_CONTEXT_ID]);
+ destroyed = uet_context_destroy(id);
+
+ return destroyed ? 0 : -ENOENT;
+}
@@ -5,13 +5,16 @@
#include <linux/types.h>
#include <net/ultraeth/uet_context.h>
+#include "uet_netlink.h"
+
static int __init uet_init(void)
{
- return 0;
+ return genl_register_family(&ultraeth_nl_family);
}
static void __exit uet_exit(void)
{
+ genl_unregister_family(&ultraeth_nl_family);
uet_context_destroy_all();
}
new file mode 100644
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/ultraeth.yaml */
+/* YNL-GEN kernel source */
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include "uet_netlink.h"
+
+#include <uapi/linux/ultraeth_nl.h>
+
+/* ULTRAETH_CMD_CONTEXT_NEW - do */
+static const struct nla_policy ultraeth_context_new_nl_policy[ULTRAETH_A_CONTEXT_ID + 1] = {
+ [ULTRAETH_A_CONTEXT_ID] = NLA_POLICY_RANGE(NLA_S32, 0, 255),
+};
+
+/* ULTRAETH_CMD_CONTEXT_DEL - do */
+static const struct nla_policy ultraeth_context_del_nl_policy[ULTRAETH_A_CONTEXT_ID + 1] = {
+ [ULTRAETH_A_CONTEXT_ID] = NLA_POLICY_RANGE(NLA_S32, 0, 255),
+};
+
+/* Ops table for ultraeth */
+static const struct genl_split_ops ultraeth_nl_ops[] = {
+ {
+ .cmd = ULTRAETH_CMD_CONTEXT_GET,
+ .dumpit = ultraeth_nl_context_get_dumpit,
+ .flags = GENL_CMD_CAP_DUMP,
+ },
+ {
+ .cmd = ULTRAETH_CMD_CONTEXT_NEW,
+ .doit = ultraeth_nl_context_new_doit,
+ .policy = ultraeth_context_new_nl_policy,
+ .maxattr = ULTRAETH_A_CONTEXT_ID,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+ {
+ .cmd = ULTRAETH_CMD_CONTEXT_DEL,
+ .doit = ultraeth_nl_context_del_doit,
+ .policy = ultraeth_context_del_nl_policy,
+ .maxattr = ULTRAETH_A_CONTEXT_ID,
+ .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+ },
+};
+
+struct genl_family ultraeth_nl_family __ro_after_init = {
+ .name = ULTRAETH_FAMILY_NAME,
+ .version = ULTRAETH_FAMILY_VERSION,
+ .netnsok = true,
+ .parallel_ops = true,
+ .module = THIS_MODULE,
+ .split_ops = ultraeth_nl_ops,
+ .n_split_ops = ARRAY_SIZE(ultraeth_nl_ops),
+};
new file mode 100644
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/ultraeth.yaml */
+/* YNL-GEN kernel header */
+
+#ifndef _LINUX_ULTRAETH_GEN_H
+#define _LINUX_ULTRAETH_GEN_H
+
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+#include <uapi/linux/ultraeth_nl.h>
+
+int ultraeth_nl_context_get_dumpit(struct sk_buff *skb,
+ struct netlink_callback *cb);
+int ultraeth_nl_context_new_doit(struct sk_buff *skb, struct genl_info *info);
+int ultraeth_nl_context_del_doit(struct sk_buff *skb, struct genl_info *info);
+
+extern struct genl_family ultraeth_nl_family;
+
+#endif /* _LINUX_ULTRAETH_GEN_H */
new file mode 100644
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/ultraeth.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_ULTRAETH_NL_H
+#define _UAPI_LINUX_ULTRAETH_NL_H
+
+#define ULTRAETH_FAMILY_NAME "ultraeth"
+#define ULTRAETH_FAMILY_VERSION 1
+
+enum {
+ ULTRAETH_A_CONTEXT_ID = 1,
+
+ __ULTRAETH_A_CONTEXT_MAX,
+ ULTRAETH_A_CONTEXT_MAX = (__ULTRAETH_A_CONTEXT_MAX - 1)
+};
+
+enum {
+ ULTRAETH_A_CONTEXTS_CONTEXT = 1,
+
+ __ULTRAETH_A_CONTEXTS_MAX,
+ ULTRAETH_A_CONTEXTS_MAX = (__ULTRAETH_A_CONTEXTS_MAX - 1)
+};
+
+enum {
+ ULTRAETH_CMD_CONTEXT_GET = 1,
+ ULTRAETH_CMD_CONTEXT_NEW,
+ ULTRAETH_CMD_CONTEXT_DEL,
+
+ __ULTRAETH_CMD_MAX,
+ ULTRAETH_CMD_MAX = (__ULTRAETH_CMD_MAX - 1)
+};
+
+#endif /* _UAPI_LINUX_ULTRAETH_NL_H */