On 16-02-23 04:44 PM, Cong Wang wrote:
On Tue, Feb 23, 2016 at 4:49 AM, Jamal Hadi Salim <j...@mojatatu.com> wrote:
+#define MODULE_ALIAS_IFE_META(metan) MODULE_ALIAS("ifemeta"
__stringify_1(metan))
+
+int get_meta_u32(struct sk_buff *skb, struct tcf_meta_info *mi);
+int get_meta_u16(struct sk_buff *skb, struct tcf_meta_info *mi);
+int tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, const void *dval);
+int alloc_meta_u32(struct tcf_meta_info *mi, void *metaval);
+int alloc_meta_u16(struct tcf_meta_info *mi, void *metaval);
+int check_meta_u32(u32 metaval, struct tcf_meta_info *mi);
+int encode_meta_u32(u32 metaval, void *skbdata, struct tcf_meta_info *mi);
+int validate_meta_u32(void *val, int len);
+int validate_meta_u16(void *val, int len);
+void release_meta_gen(struct tcf_meta_info *mi);
+int register_ife_op(struct tcf_meta_ops *mops);
+int unregister_ife_op(struct tcf_meta_ops *mops);
These are exported to other modules, please add some prefix to protect them.
suggestion? I thought they seemed unique enough.
+ * copyright Jamal Hadi Salim (2015)
2016? ;)
Yes. This code has been around since then. Actually earlier than that
running. But i formatted it for kernel inclusion in about first week
of January. Dave asked me to wait for the ethertype to get it in.
The IETF still hasnt come through a year later and so i re-submitted
with no default ethertype. I think 2015 is deserving here, no?
I hope i dont spend another year discussing on the list ;-> /me runs
+ return 8;
Why 8?
Magic number;-> I will add a comment.
It is a TLV that includes 4 bytes. I am going to wait for
comments to settle then make an update.
+
+
+int alloc_meta_u32(struct tcf_meta_info *mi, void *metaval)
+{
+ mi->metaval = kzalloc(sizeof(u32), GFP_KERNEL);
+ if (!mi->metaval)
+ return -ENOMEM;
+
+ memcpy(mi->metaval, metaval, 4);
kmemdup()?
Sure. I'll take care of the rest you pointed to.
No need to initi it since list_add_tail() is just one line below.
+ list_add_tail(&mops->list, &ifeoplist);
+ write_unlock(&ife_mod_lock);
+ return 0;
+}
+
+int unregister_ife_op(struct tcf_meta_ops *mops)
+{
+ struct tcf_meta_ops *m;
+ int err = -ENOENT;
+
+ write_lock(&ife_mod_lock);
+ list_for_each_entry(m, &ifeoplist, list) {
+ if (m->metaid == mops->metaid) {
+ list_del(&mops->list);
+ err = 0;
+ break;
+ }
+ }
+ write_unlock(&ife_mod_lock);
+
+ return err;
+}
+
+EXPORT_SYMBOL_GPL(register_ife_op);
+EXPORT_SYMBOL_GPL(unregister_ife_op);
Move them next to their definitions.
+
+void print_ife_oplist(void)
+{
+ struct tcf_meta_ops *o;
+ int i = 0;
+
+ read_lock(&ife_mod_lock);
+ list_for_each_entry(o, &ifeoplist, list) {
+ pr_debug("%d: %s metaid %d\n", ++i, o->name, o->metaid);
+ }
+ read_unlock(&ife_mod_lock);
+}
+
+/* called when adding new meta information
+ * under ife->tcf_lock
+*/
+int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
+ void *val, int len)
I failed to understand the name of this function.
It tries to load a metadata kernel module and vets (or validates)
the passed parameters from user space.
Suggestions?
+{
+ struct tcf_meta_ops *ops = find_ife_oplist(metaid);
+ int ret = 0;
+
+ if (!ops) {
+ ret = -ENOENT;
+#ifdef CONFIG_MODULES
+ spin_unlock_bh(&ife->tcf_lock);
+ rtnl_unlock();
+ request_module("ifemeta%u", metaid);
+ rtnl_lock();
+ spin_lock_bh(&ife->tcf_lock);
+ ops = find_ife_oplist(metaid);
+#endif
+ }
+
+ if (ops) {
+ ret = 0;
+
+ /* XXX: unfortunately cant use nla_policy at this point
+ * because a length of 0 is valid in the case of
+ * "allow". "use" semantics do enforce for proper
+ * length and i couldve use nla_policy but it makes it hard
+ * to use it just for that..
+ */
+ if (len) {
+ if (ops->validate) {
+ ret = ops->validate(val, len);
+ } else {
+ if (ops->metatype == NLA_U32) {
+ ret = validate_meta_u32(val, len);
+ } else if (ops->metatype == NLA_U16) {
+ ret = validate_meta_u16(val, len);
+ }
+ }
+ }
Sounds like this should be in a separated function.
Could be.
+int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, int len)
+{
+ struct tcf_meta_info *mi = NULL;
+ struct tcf_meta_ops *ops = find_ife_oplist(metaid);
+ int ret = 0;
+
+ if (!ops) {
+ return -ENOENT;
+ }
+
+ mi = kzalloc(sizeof(*mi), GFP_KERNEL);
+ if (!mi) {
+ /*put back what find_ife_oplist took */
+ module_put(ops->owner);
+ return -ENOMEM;
+ }
+
+ mi->metaid = metaid;
+ mi->ops = ops;
+ if (len > 0) {
+ ret = ops->alloc(mi, metaval);
+ if (ret != 0) {
+ kfree(mi);
+ module_put(ops->owner);
+ return ret;
+ }
+ }
+
+ /*XXX: if it becomes necessary add per tcf_meta_info lock;
+ * for now use Thor's hammer */
What about ife->tcf_lock?
I'll walk the code paths and check - it may be enough.
+ write_lock(&ife_mod_lock);
+ list_add_tail(&mi->metalist, &ife->metalist);
+ write_unlock(&ife_mod_lock);
+
+ if ((parm->flags & IFE_ENCODE) && (parm->flags & IFE_DECODE)) {
+ pr_info("Ambigous: Cant have both encode and decode\n");
+ return -EINVAL;
+ }
Is it possible to fold them into one bit?
As in the check you mean?
+static struct tc_action_ops act_ife_ops = {
+ .kind = "ife",
+ .type = TCA_ACT_IFE,
+ .owner = THIS_MODULE,
+ .act = tcf_ife,
+ .dump = tcf_ife_dump,
+ .cleanup = tcf_ife_cleanup,
+ .init = tcf_ife_init,
+};
+
+static int __init ife_init_module(void)
+{
+ pr_info("Loaded IFE maximum metaid %d\n", max_metacnt);
Not needed, people can use lsmod to figure it out.
Yeah - missed that one after Daniel's earlier comment.
+ INIT_LIST_HEAD(&ifeoplist);
It is already initialized statically.
Good catch.
+module_param(max_metacnt, int, 0);
I am sure DaveM doesn't like this.
You know what - i will take this thing out. Daniel doesnt like it
either.
Need to figure a different way to achieve the same goals.
Ok, when the noise settles i will make another release.
cheers,
jamal