In commit cad2929dc432 ("tipc: update a binding service via broadcast"),
We use broadcast to update a binding service for a large cluster.
However, if we try to publish a thousands of services at the
same time, we may to get "link overflow" happen because of queue limit
had reached.

We now introduce a smooth change to replicast if the broadcast link has
reach to the limit of queue.

Signed-off-by: Hoang Huu Le <hoang.h...@dektech.com.au>
---
 net/tipc/link.c |  5 ++++-
 net/tipc/node.c | 12 ++++++++++--
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/net/tipc/link.c b/net/tipc/link.c
index 06b880da2a8e..ca908ead753a 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1022,7 +1022,10 @@ int tipc_link_xmit(struct tipc_link *l, struct 
sk_buff_head *list,
        /* Allow oversubscription of one data msg per source at congestion */
        if (unlikely(l->backlog[imp].len >= l->backlog[imp].limit)) {
                if (imp == TIPC_SYSTEM_IMPORTANCE) {
-                       pr_warn("%s<%s>, link overflow", link_rst_msg, l->name);
+                       pr_warn_ratelimited("%s<%s>, link overflow",
+                                           link_rst_msg, l->name);
+                       if (link_is_bc_sndlink(l))
+                               return -EOVERFLOW;
                        return -ENOBUFS;
                }
                rc = link_schedule_user(l, hdr);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index d269ebe382e1..a37976610367 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1750,15 +1750,23 @@ void tipc_node_broadcast(struct net *net, struct 
sk_buff *skb, int rc_dests)
        struct tipc_node *n;
        u16 dummy;
        u32 dst;
+       int rc = 0;
 
        /* Use broadcast if all nodes support it */
        if (!rc_dests && tipc_bcast_get_mode(net) != BCLINK_MODE_RCAST) {
+               txskb = pskb_copy(skb, GFP_ATOMIC);
+               if (!txskb)
+                       goto rcast;
                __skb_queue_head_init(&xmitq);
-               __skb_queue_tail(&xmitq, skb);
-               tipc_bcast_xmit(net, &xmitq, &dummy);
+               __skb_queue_tail(&xmitq, txskb);
+               rc = tipc_bcast_xmit(net, &xmitq, &dummy);
+               if (rc == -EOVERFLOW)
+                       goto rcast;
+               kfree_skb(skb);
                return;
        }
 
+rcast:
        /* Otherwise use legacy replicast method */
        rcu_read_lock();
        list_for_each_entry_rcu(n, tipc_nodes(net), list) {
-- 
2.25.1



_______________________________________________
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to