Signed-off-by: Ahmed Amamou <ah...@gandi.net>
---
 net/bridge/rbr_rtnetlink.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/net/bridge/rbr_rtnetlink.c b/net/bridge/rbr_rtnetlink.c
index 5b6dab4..23fd0d7 100644
--- a/net/bridge/rbr_rtnetlink.c
+++ b/net/bridge/rbr_rtnetlink.c
@@ -42,7 +42,50 @@ int rbr_set_data(struct net_device *dev, struct nlattr *tb[],
                nick = nla_get_u16(data[IFLA_TRILL_ROOT]);
                err = set_treeroot(br->rbr, htons(nick));
        }
+       if (data[IFLA_TRILL_INFO]) {
+               struct rbr_nickinfo *rbr_ni;
+               struct rbr_node *old;
+               size_t old_size = 0;
+               size_t size = 0;
+               struct rbr *rbr;
 
+               if (!br->rbr)
+                       return -EINVAL;
+
+               rbr = br->rbr;
+               size = nla_len(data[IFLA_TRILL_INFO]);
+               rbr_ni = kzalloc(size, GFP_KERNEL);
+               if (!rbr_ni)
+                       goto fail;
+               memcpy(rbr_ni, nla_data(data[IFLA_TRILL_INFO]), size);
+               nick = rbr_ni->nick;
+               old = br->rbr->rbr_nodes[nick];
+               if (old)
+                       old_size = RBR_NI_TOTALSIZE(old->rbr_ni);
+               /* replace old node by a new one only if nickname
+                * information have changed
+                */
+               if (!old || old_size != size ||
+                   memcmp(old->rbr_ni, rbr_ni, size)) {
+                       struct rbr_node *new;
+
+                       new = kzalloc(sizeof(*old), GFP_KERNEL);
+                       if (!new) {
+                               kfree(rbr_ni);
+                               goto fail;
+                       }
+                       atomic_set(&new->refs, 1);
+                       new->rbr_ni = rbr_ni;
+                       /* Avoid deleting node while it is been used for
+                        * routing
+                        */
+                       rcu_assign_pointer(rbr->rbr_nodes[nick], new);
+                       if (old)
+                               rbr_node_put(old);
+               } else {
+                       kfree(rbr_ni);
+               }
+       }
        return 0;
 fail:
        pr_warn("rbr_set_data FAILED\n");
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to