b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /* |
| 2 | * Fastpath Netlink Interface |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU FP_ERR( Public License |
| 6 | * as published by the Free Software Foundation; either version |
| 7 | * 2 of the License, or (at your option) any later version. |
| 8 | */ |
| 9 | |
| 10 | #define pr_fmt(fmt) "mfp" " netlink:%s:%d: " fmt, __func__, __LINE__ |
| 11 | |
| 12 | #include "fp_common.h" |
| 13 | #include "fp_core.h" |
| 14 | #include "fp_netlink.h" |
| 15 | |
| 16 | struct nla_policy fp_netlink_policy[FASTPATH_NL_A_MAX + 1] __maybe_unused = { |
| 17 | [FASTPATH_NL_A_MSG] = { .type = NLA_NUL_STRING }, |
| 18 | }; |
| 19 | |
| 20 | /* Optional: Add rule parsing to avoid blocking all entries */ |
| 21 | static int fp_netlink_ipt_notify(struct sk_buff *skb, struct genl_info *info) |
| 22 | { |
| 23 | struct fastpath_module *m = fp_module_get_by_name("fp_learner"); |
| 24 | int ret = -EINVAL; |
| 25 | |
| 26 | if (!m) { |
| 27 | pr_err("failed to get fp_learner module\n"); |
| 28 | return -EINVAL; |
| 29 | } |
| 30 | |
| 31 | if (m->ops && m->ops->ioctl) { |
| 32 | ret = m->ops->ioctl(m, FASTPATH_NL_C_IPT_NOTIFY, NULL); |
| 33 | goto out; |
| 34 | } |
| 35 | |
| 36 | out: |
| 37 | fp_module_put(m); |
| 38 | return ret; |
| 39 | } |
| 40 | |
| 41 | static struct genl_ops fp_netlink_genl_ops[] = { |
| 42 | FASTPATH_NL_OP(FASTPATH_NL_C_IPT_NOTIFY, fp_netlink_ipt_notify), |
| 43 | }; |
| 44 | |
| 45 | static struct genl_family fp_netlink_family = { |
| 46 | .hdrsize = 0, |
| 47 | .name = "FASTPATH", |
| 48 | .version = 1, |
| 49 | .maxattr = FASTPATH_NL_A_MAX, |
| 50 | .ops = fp_netlink_genl_ops, |
| 51 | .n_ops = ARRAY_SIZE(fp_netlink_genl_ops), |
| 52 | }; |
| 53 | |
| 54 | static struct attribute *fp_netlink_attrs[] = { |
| 55 | NULL, /* need to NULL terminate the list of attributes */ |
| 56 | }; |
| 57 | |
| 58 | static void fp_netlink_release(struct kobject *kobj) |
| 59 | { |
| 60 | struct fastpath_module *module = to_fpmod(kobj); |
| 61 | |
| 62 | genl_unregister_family(&fp_netlink_family); |
| 63 | |
| 64 | pr_debug("fp_netlink released\n"); |
| 65 | kfree(module); |
| 66 | } |
| 67 | |
| 68 | static struct kobj_type ktype_netlink = { |
| 69 | .sysfs_ops = &fp_sysfs_ops, |
| 70 | .default_attrs = fp_netlink_attrs, |
| 71 | .release = fp_netlink_release, |
| 72 | }; |
| 73 | |
| 74 | static int fp_netlink_probe(struct fastpath_module *module) |
| 75 | { |
| 76 | int ret; |
| 77 | |
| 78 | |
| 79 | module->priv = NULL; |
| 80 | snprintf(module->name, sizeof(module->name),"fp_netlink"); |
| 81 | |
| 82 | ret = genl_register_family(&fp_netlink_family); |
| 83 | |
| 84 | kobject_init(&module->kobj, &ktype_netlink); |
| 85 | ret = kobject_add(&module->kobj, module->fastpath->kobj, "%s", module->name); |
| 86 | if (ret < 0) { |
| 87 | pr_err("kobject_add failed (%d)\n", ret); |
| 88 | goto err_register_ops; |
| 89 | } |
| 90 | |
| 91 | kobject_uevent(&module->kobj, KOBJ_ADD); |
| 92 | |
| 93 | pr_debug("fp_netlink probed\n"); |
| 94 | return 0; |
| 95 | |
| 96 | err_register_ops: |
| 97 | kobject_put(&module->kobj); |
| 98 | genl_unregister_family(&fp_netlink_family); |
| 99 | |
| 100 | return ret; |
| 101 | } |
| 102 | |
| 103 | static int fp_netlink_remove(struct fastpath_module *module) |
| 104 | { |
| 105 | kobject_put(&module->kobj); |
| 106 | |
| 107 | pr_debug("fp_netlink removed\n"); |
| 108 | return 0; |
| 109 | } |
| 110 | |
| 111 | struct fastpath_module_ops fp_netlink_ops = { |
| 112 | .probe = fp_netlink_probe, |
| 113 | .remove = fp_netlink_remove, |
| 114 | }; |