]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/tipc/name_table.c
Merge tag 'fbdev-v4.11' of git://github.com/bzolnier/linux
[karo-tx-linux.git] / net / tipc / name_table.c
index e190460fe0d396e795da064c9c3fe4523177879c..9be6592e4a6fa20c78995396ffa3dfcd1f19537a 100644 (file)
@@ -608,7 +608,7 @@ not_found:
  * Returns non-zero if any off-node ports overlap
  */
 int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
-                             u32 limit, struct tipc_plist *dports)
+                             u32 limit, struct list_head *dports)
 {
        struct name_seq *seq;
        struct sub_seq *sseq;
@@ -633,7 +633,7 @@ int tipc_nametbl_mc_translate(struct net *net, u32 type, u32 lower, u32 upper,
                info = sseq->info;
                list_for_each_entry(publ, &info->node_list, node_list) {
                        if (publ->scope <= limit)
-                               tipc_plist_push(dports, publ->ref);
+                               u32_push(dports, publ->ref);
                }
 
                if (info->cluster_list_size != info->node_list_size)
@@ -645,6 +645,39 @@ exit:
        return res;
 }
 
+/* tipc_nametbl_lookup_dst_nodes - find broadcast destination nodes
+ * - Creates list of nodes that overlap the given multicast address
+ * - Determines if any node local ports overlap
+ */
+void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
+                                  u32 upper, u32 domain,
+                                  struct tipc_nlist *nodes)
+{
+       struct sub_seq *sseq, *stop;
+       struct publication *publ;
+       struct name_info *info;
+       struct name_seq *seq;
+
+       rcu_read_lock();
+       seq = nametbl_find_seq(net, type);
+       if (!seq)
+               goto exit;
+
+       spin_lock_bh(&seq->lock);
+       sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
+       stop = seq->sseqs + seq->first_free;
+       for (; sseq->lower <= upper && sseq != stop; sseq++) {
+               info = sseq->info;
+               list_for_each_entry(publ, &info->zone_list, zone_list) {
+                       if (tipc_in_scope(domain, publ->node))
+                               tipc_nlist_add(nodes, publ->node);
+               }
+       }
+       spin_unlock_bh(&seq->lock);
+exit:
+       rcu_read_unlock();
+}
+
 /*
  * tipc_nametbl_publish - add name publication to network name tables
  */
@@ -1022,40 +1055,79 @@ int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 }
 
-void tipc_plist_push(struct tipc_plist *pl, u32 port)
+bool u32_find(struct list_head *l, u32 value)
 {
-       struct tipc_plist *nl;
+       struct u32_item *item;
 
-       if (likely(!pl->port)) {
-               pl->port = port;
-               return;
+       list_for_each_entry(item, l, list) {
+               if (item->value == value)
+                       return true;
        }
-       if (pl->port == port)
-               return;
-       list_for_each_entry(nl, &pl->list, list) {
-               if (nl->port == port)
-                       return;
+       return false;
+}
+
+bool u32_push(struct list_head *l, u32 value)
+{
+       struct u32_item *item;
+
+       list_for_each_entry(item, l, list) {
+               if (item->value == value)
+                       return false;
+       }
+       item = kmalloc(sizeof(*item), GFP_ATOMIC);
+       if (unlikely(!item))
+               return false;
+
+       item->value = value;
+       list_add(&item->list, l);
+       return true;
+}
+
+u32 u32_pop(struct list_head *l)
+{
+       struct u32_item *item;
+       u32 value = 0;
+
+       if (list_empty(l))
+               return 0;
+       item = list_first_entry(l, typeof(*item), list);
+       value = item->value;
+       list_del(&item->list);
+       kfree(item);
+       return value;
+}
+
+bool u32_del(struct list_head *l, u32 value)
+{
+       struct u32_item *item, *tmp;
+
+       list_for_each_entry_safe(item, tmp, l, list) {
+               if (item->value != value)
+                       continue;
+               list_del(&item->list);
+               kfree(item);
+               return true;
        }
-       nl = kmalloc(sizeof(*nl), GFP_ATOMIC);
-       if (nl) {
-               nl->port = port;
-               list_add(&nl->list, &pl->list);
+       return false;
+}
+
+void u32_list_purge(struct list_head *l)
+{
+       struct u32_item *item, *tmp;
+
+       list_for_each_entry_safe(item, tmp, l, list) {
+               list_del(&item->list);
+               kfree(item);
        }
 }
 
-u32 tipc_plist_pop(struct tipc_plist *pl)
+int u32_list_len(struct list_head *l)
 {
-       struct tipc_plist *nl;
-       u32 port = 0;
+       struct u32_item *item;
+       int i = 0;
 
-       if (likely(list_empty(&pl->list))) {
-               port = pl->port;
-               pl->port = 0;
-               return port;
+       list_for_each_entry(item, l, list) {
+               i++;
        }
-       nl = list_first_entry(&pl->list, typeof(*nl), list);
-       port = nl->port;
-       list_del(&nl->list);
-       kfree(nl);
-       return port;
+       return i;
 }