-----Original Message----- From: Jon Maloy <jma...@redhat.com> Sent: Monday, June 8, 2020 2:14 AM To: tipc-discussion@lists.sourceforge.net Subject: Re: [tipc-discussion] [net-next] tipc: update a binding service via broadcast
On 6/7/20 3:03 PM, Jon Maloy wrote: > > > On 6/7/20 12:24 AM, Hoang Huu Le wrote: >> Currently, updating binding table (add service binding to >> name table/withdraw a service binding) is being sent over replicast. >> However, if we are scaling up clusters to > 100 nodes/containers this >> method is less affection because of looping through nodes in a >> cluster one >> by one. >> >> It is worth to use broadcast to update a binding service. This way, the >> binding table can be updated on all peer nodes in one shot. >> >> Broadcast is used when all peer nodes, as indicated by a new capability >> flag TIPC_NAMED_BCAST, support reception of this message type. >> >> Four problems need to be considered when introducing this feature. >> 1) When establishing a link to a new peer node we still update this by a >> unicast 'bulk' update. This may lead to race conditions, where a later >> broadcast publication/withdrawal bypass the 'bulk', resulting in >> disordered publications, or even that a withdrawal may arrive before the >> corresponding publication. We solve this by adding an 'is_last_bulk' bit >> in the last bulk messages so that it can be distinguished from all other >> messages. Only when this message has arrived do we open up for reception >> of broadcast publications/withdrawals. > Add a line feed between these paragraphs before you send the patch. > Otherwise, still acked by me. > > ///jon Oh, already posted... Just ignore my comment above. [Hoang] net-next is closed. I will re-post the patch later with your suggestion. ///jon > >> 2) When a first legacy node is added to the cluster all distribution >> will switch over to use the legacy 'replicast' method, while the >> opposite happens when the last legacy node leaves the cluster. This >> entails another risk of message disordering that has to be handled. We >> solve this by adding a sequence number to the broadcast/replicast >> messages, so that disordering can be discovered and corrected. Note >> however that we don't need to consider potential message loss or >> duplication at this protocol level. >> 3) Bulk messages don't contain any sequence numbers, and will always >> arrive in order. Hence we must exempt those from the sequence number >> control and deliver them unconditionally. We solve this by adding a new >> 'is_bulk' bit in those messages so that they can be recognized. >> 4) Legacy messages, which don't contain any new bits or sequence >> numbers, but neither can arrive out of order, also need to be exempt >> from the initial synchronization and sequence number check, and >> delivered unconditionally. Therefore, we add another 'is_not_legacy' bit >> to all new messages so that those can be distinguished from legacy >> messages and the latter delivered directly. >> >> Signed-off-by: Hoang Huu Le <hoang.h...@dektech.com.au> >> Acked-by: Jon Maloy <jma...@redhat.com> >> --- >> net/tipc/bcast.c | 6 +-- >> net/tipc/bcast.h | 4 +- >> net/tipc/link.c | 2 +- >> net/tipc/msg.h | 40 ++++++++++++++++ >> net/tipc/name_distr.c | 109 +++++++++++++++++++++++++++++++----------- >> net/tipc/name_distr.h | 9 ++-- >> net/tipc/name_table.c | 9 +++- >> net/tipc/name_table.h | 2 + >> net/tipc/node.c | 29 ++++++++--- >> net/tipc/node.h | 8 ++-- >> 10 files changed, 170 insertions(+), 48 deletions(-) >> >> diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c >> index 383f87bc1061..940d176e0e87 100644 >> --- a/net/tipc/bcast.c >> +++ b/net/tipc/bcast.c >> @@ -250,8 +250,8 @@ static void tipc_bcast_select_xmit_method(struct >> net *net, int dests, >> * Consumes the buffer chain. >> * Returns 0 if success, otherwise errno: -EHOSTUNREACH,-EMSGSIZE >> */ >> -static int tipc_bcast_xmit(struct net *net, struct sk_buff_head *pkts, >> - u16 *cong_link_cnt) >> +int tipc_bcast_xmit(struct net *net, struct sk_buff_head *pkts, >> + u16 *cong_link_cnt) >> { >> struct tipc_link *l = tipc_bc_sndlink(net); >> struct sk_buff_head xmitq; >> @@ -752,7 +752,7 @@ void tipc_nlist_purge(struct tipc_nlist *nl) >> nl->local = false; >> } >> -u32 tipc_bcast_get_broadcast_mode(struct net *net) >> +u32 tipc_bcast_get_mode(struct net *net) >> { >> struct tipc_bc_base *bb = tipc_bc_base(net); >> diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h >> index 4240c95188b1..2d9352dc7b0e 100644 >> --- a/net/tipc/bcast.h >> +++ b/net/tipc/bcast.h >> @@ -90,6 +90,8 @@ void tipc_bcast_toggle_rcast(struct net *net, bool >> supp); >> int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts, >> struct tipc_mc_method *method, struct tipc_nlist *dests, >> u16 *cong_link_cnt); >> +int tipc_bcast_xmit(struct net *net, struct sk_buff_head *pkts, >> + u16 *cong_link_cnt); >> int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct >> sk_buff *skb); >> void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, >> struct tipc_msg *hdr); >> @@ -101,7 +103,7 @@ int tipc_nl_add_bc_link(struct net *net, struct >> tipc_nl_msg *msg, >> int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]); >> int tipc_bclink_reset_stats(struct net *net, struct tipc_link *l); >> -u32 tipc_bcast_get_broadcast_mode(struct net *net); >> +u32 tipc_bcast_get_mode(struct net *net); >> u32 tipc_bcast_get_broadcast_ratio(struct net *net); >> void tipc_mcast_filter_msg(struct net *net, struct sk_buff_head >> *defq, >> diff --git a/net/tipc/link.c b/net/tipc/link.c >> index ee3b8d0576b8..eac89a3e22ce 100644 >> --- a/net/tipc/link.c >> +++ b/net/tipc/link.c >> @@ -2745,7 +2745,7 @@ int tipc_nl_add_bc_link(struct net *net, struct >> tipc_nl_msg *msg, >> void *hdr; >> struct nlattr *attrs; >> struct nlattr *prop; >> - u32 bc_mode = tipc_bcast_get_broadcast_mode(net); >> + u32 bc_mode = tipc_bcast_get_mode(net); >> u32 bc_ratio = tipc_bcast_get_broadcast_ratio(net); >> if (!bcl) >> diff --git a/net/tipc/msg.h b/net/tipc/msg.h >> index 58660d56bc83..65119e81ff0c 100644 >> --- a/net/tipc/msg.h >> +++ b/net/tipc/msg.h >> @@ -438,6 +438,36 @@ static inline void msg_set_errcode(struct >> tipc_msg *m, u32 err) >> msg_set_bits(m, 1, 25, 0xf, err); >> } >> +static inline void msg_set_bulk(struct tipc_msg *m) >> +{ >> + msg_set_bits(m, 1, 28, 0x1, 1); >> +} >> + >> +static inline u32 msg_is_bulk(struct tipc_msg *m) >> +{ >> + return msg_bits(m, 1, 28, 0x1); >> +} >> + >> +static inline void msg_set_last_bulk(struct tipc_msg *m) >> +{ >> + msg_set_bits(m, 1, 27, 0x1, 1); >> +} >> + >> +static inline u32 msg_is_last_bulk(struct tipc_msg *m) >> +{ >> + return msg_bits(m, 1, 27, 0x1); >> +} >> + >> +static inline void msg_set_non_legacy(struct tipc_msg *m) >> +{ >> + msg_set_bits(m, 1, 26, 0x1, 1); >> +} >> + >> +static inline u32 msg_is_legacy(struct tipc_msg *m) >> +{ >> + return !msg_bits(m, 1, 26, 0x1); >> +} >> + >> static inline u32 msg_reroute_cnt(struct tipc_msg *m) >> { >> return msg_bits(m, 1, 21, 0xf); >> @@ -567,6 +597,16 @@ static inline void msg_set_origport(struct >> tipc_msg *m, u32 p) >> msg_set_word(m, 4, p); >> } >> +static inline u16 msg_named_seqno(struct tipc_msg *m) >> +{ >> + return msg_bits(m, 4, 0, 0xffff); >> +} >> + >> +static inline void msg_set_named_seqno(struct tipc_msg *m, u16 n) >> +{ >> + msg_set_bits(m, 4, 0, 0xffff, n); >> +} >> + >> static inline u32 msg_destport(struct tipc_msg *m) >> { >> return msg_word(m, 5); >> diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c >> index 5feaf3b67380..481d480609f0 100644 >> --- a/net/tipc/name_distr.c >> +++ b/net/tipc/name_distr.c >> @@ -102,7 +102,8 @@ struct sk_buff *tipc_named_publish(struct net >> *net, struct publication *publ) >> pr_warn("Publication distribution failure\n"); >> return NULL; >> } >> - >> + msg_set_named_seqno(buf_msg(skb), nt->snd_nxt++); >> + msg_set_non_legacy(buf_msg(skb)); >> item = (struct distr_item *)msg_data(buf_msg(skb)); >> publ_to_item(item, publ); >> return skb; >> @@ -114,8 +115,8 @@ struct sk_buff *tipc_named_publish(struct net >> *net, struct publication *publ) >> struct sk_buff *tipc_named_withdraw(struct net *net, struct >> publication *publ) >> { >> struct name_table *nt = tipc_name_table(net); >> - struct sk_buff *buf; >> struct distr_item *item; >> + struct sk_buff *skb; >> write_lock_bh(&nt->cluster_scope_lock); >> list_del(&publ->binding_node); >> @@ -123,15 +124,16 @@ struct sk_buff *tipc_named_withdraw(struct net >> *net, struct publication *publ) >> if (publ->scope == TIPC_NODE_SCOPE) >> return NULL; >> - buf = named_prepare_buf(net, WITHDRAWAL, ITEM_SIZE, 0); >> - if (!buf) { >> + skb = named_prepare_buf(net, WITHDRAWAL, ITEM_SIZE, 0); >> + if (!skb) { >> pr_warn("Withdrawal distribution failure\n"); >> return NULL; >> } >> - >> - item = (struct distr_item *)msg_data(buf_msg(buf)); >> + msg_set_named_seqno(buf_msg(skb), nt->snd_nxt++); >> + msg_set_non_legacy(buf_msg(skb)); >> + item = (struct distr_item *)msg_data(buf_msg(skb)); >> publ_to_item(item, publ); >> - return buf; >> + return skb; >> } >> /** >> @@ -141,7 +143,7 @@ struct sk_buff *tipc_named_withdraw(struct net >> *net, struct publication *publ) >> * @pls: linked list of publication items to be packed into buffer >> chain >> */ >> static void named_distribute(struct net *net, struct sk_buff_head >> *list, >> - u32 dnode, struct list_head *pls) >> + u32 dnode, struct list_head *pls, u16 seqno) >> { >> struct publication *publ; >> struct sk_buff *skb = NULL; >> @@ -149,6 +151,7 @@ static void named_distribute(struct net *net, >> struct sk_buff_head *list, >> u32 msg_dsz = ((tipc_node_get_mtu(net, dnode, 0, false) - >> INT_H_SIZE) / >> ITEM_SIZE) * ITEM_SIZE; >> u32 msg_rem = msg_dsz; >> + struct tipc_msg *hdr; >> list_for_each_entry(publ, pls, binding_node) { >> /* Prepare next buffer: */ >> @@ -159,8 +162,11 @@ static void named_distribute(struct net *net, >> struct sk_buff_head *list, >> pr_warn("Bulk publication failure\n"); >> return; >> } >> - msg_set_bc_ack_invalid(buf_msg(skb), true); >> - item = (struct distr_item *)msg_data(buf_msg(skb)); >> + hdr = buf_msg(skb); >> + msg_set_bc_ack_invalid(hdr, true); >> + msg_set_bulk(hdr); >> + msg_set_non_legacy(hdr); >> + item = (struct distr_item *)msg_data(hdr); >> } >> /* Pack publication into message: */ >> @@ -176,24 +182,35 @@ static void named_distribute(struct net *net, >> struct sk_buff_head *list, >> } >> } >> if (skb) { >> - msg_set_size(buf_msg(skb), INT_H_SIZE + (msg_dsz - msg_rem)); >> + hdr = buf_msg(skb); >> + msg_set_size(hdr, INT_H_SIZE + (msg_dsz - msg_rem)); >> skb_trim(skb, INT_H_SIZE + (msg_dsz - msg_rem)); >> __skb_queue_tail(list, skb); >> } >> + hdr = buf_msg(skb_peek_tail(list)); >> + msg_set_last_bulk(hdr); >> + msg_set_named_seqno(hdr, seqno); >> } >> /** >> * tipc_named_node_up - tell specified node about all publications >> by this node >> */ >> -void tipc_named_node_up(struct net *net, u32 dnode) >> +void tipc_named_node_up(struct net *net, u32 dnode, u16 capabilities) >> { >> struct name_table *nt = tipc_name_table(net); >> + struct tipc_net *tn = tipc_net(net); >> struct sk_buff_head head; >> + u16 seqno; >> __skb_queue_head_init(&head); >> + spin_lock_bh(&tn->nametbl_lock); >> + if (!(capabilities & TIPC_NAMED_BCAST)) >> + nt->rc_dests++; >> + seqno = nt->snd_nxt; >> + spin_unlock_bh(&tn->nametbl_lock); >> read_lock_bh(&nt->cluster_scope_lock); >> - named_distribute(net, &head, dnode, &nt->cluster_scope); >> + named_distribute(net, &head, dnode, &nt->cluster_scope, seqno); >> tipc_node_xmit(net, &head, dnode, 0); >> read_unlock_bh(&nt->cluster_scope_lock); >> } >> @@ -245,13 +262,21 @@ static void tipc_dist_queue_purge(struct net >> *net, u32 addr) >> spin_unlock_bh(&tn->nametbl_lock); >> } >> -void tipc_publ_notify(struct net *net, struct list_head >> *nsub_list, u32 addr) >> +void tipc_publ_notify(struct net *net, struct list_head *nsub_list, >> + u32 addr, u16 capabilities) >> { >> + struct name_table *nt = tipc_name_table(net); >> + struct tipc_net *tn = tipc_net(net); >> + >> struct publication *publ, *tmp; >> list_for_each_entry_safe(publ, tmp, nsub_list, binding_node) >> tipc_publ_purge(net, publ, addr); >> tipc_dist_queue_purge(net, addr); >> + spin_lock_bh(&tn->nametbl_lock); >> + if (!(capabilities & TIPC_NAMED_BCAST)) >> + nt->rc_dests--; >> + spin_unlock_bh(&tn->nametbl_lock); >> } >> /** >> @@ -295,29 +320,55 @@ static bool tipc_update_nametbl(struct net >> *net, struct distr_item *i, >> return false; >> } >> +struct sk_buff *tipc_named_dequeue(struct sk_buff_head *namedq, >> + u16 *rcv_nxt, bool *open) >> +{ >> + struct sk_buff *skb, *tmp; >> + struct tipc_msg *hdr; >> + u16 seqno; >> + >> + skb_queue_walk_safe(namedq, skb, tmp) { >> + skb_linearize(skb); >> + hdr = buf_msg(skb); >> + seqno = msg_named_seqno(hdr); >> + if (msg_is_last_bulk(hdr)) { >> + *rcv_nxt = seqno; >> + *open = true; >> + } >> + if (msg_is_bulk(hdr) || msg_is_legacy(hdr)) { >> + __skb_unlink(skb, namedq); >> + return skb; >> + } >> + >> + if (*open && (*rcv_nxt == seqno)) { >> + (*rcv_nxt)++; >> + __skb_unlink(skb, namedq); >> + return skb; >> + } >> + } >> + return NULL; >> +} >> + >> /** >> * tipc_named_rcv - process name table update messages sent by >> another node >> */ >> -void tipc_named_rcv(struct net *net, struct sk_buff_head *inputq) >> +void tipc_named_rcv(struct net *net, struct sk_buff_head *namedq, >> + u16 *rcv_nxt, bool *open) >> { >> - struct tipc_net *tn = net_generic(net, tipc_net_id); >> - struct tipc_msg *msg; >> + struct tipc_net *tn = tipc_net(net); >> struct distr_item *item; >> - uint count; >> - u32 node; >> + struct tipc_msg *hdr; >> struct sk_buff *skb; >> - int mtype; >> + u32 count, node = 0; >> spin_lock_bh(&tn->nametbl_lock); >> - for (skb = skb_dequeue(inputq); skb; skb = skb_dequeue(inputq)) { >> - skb_linearize(skb); >> - msg = buf_msg(skb); >> - mtype = msg_type(msg); >> - item = (struct distr_item *)msg_data(msg); >> - count = msg_data_sz(msg) / ITEM_SIZE; >> - node = msg_orignode(msg); >> + while ((skb = tipc_named_dequeue(namedq, rcv_nxt, open))) { >> + hdr = buf_msg(skb); >> + node = msg_orignode(hdr); >> + item = (struct distr_item *)msg_data(hdr); >> + count = msg_data_sz(hdr) / ITEM_SIZE; >> while (count--) { >> - tipc_update_nametbl(net, item, node, mtype); >> + tipc_update_nametbl(net, item, node, msg_type(hdr)); >> item++; >> } >> kfree_skb(skb); >> @@ -345,6 +396,6 @@ void tipc_named_reinit(struct net *net) >> publ->node = self; >> list_for_each_entry_rcu(publ, &nt->cluster_scope, binding_node) >> publ->node = self; >> - >> + nt->rc_dests = 0; >> spin_unlock_bh(&tn->nametbl_lock); >> } >> diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h >> index 63fc73e0fa6c..092323158f06 100644 >> --- a/net/tipc/name_distr.h >> +++ b/net/tipc/name_distr.h >> @@ -67,11 +67,14 @@ struct distr_item { >> __be32 key; >> }; >> +void tipc_named_bcast(struct net *net, struct sk_buff *skb); >> struct sk_buff *tipc_named_publish(struct net *net, struct >> publication *publ); >> struct sk_buff *tipc_named_withdraw(struct net *net, struct >> publication *publ); >> -void tipc_named_node_up(struct net *net, u32 dnode); >> -void tipc_named_rcv(struct net *net, struct sk_buff_head *msg_queue); >> +void tipc_named_node_up(struct net *net, u32 dnode, u16 capabilities); >> +void tipc_named_rcv(struct net *net, struct sk_buff_head *namedq, >> + u16 *rcv_nxt, bool *open); >> void tipc_named_reinit(struct net *net); >> -void tipc_publ_notify(struct net *net, struct list_head *nsub_list, >> u32 addr); >> +void tipc_publ_notify(struct net *net, struct list_head *nsub_list, >> + u32 addr, u16 capabilities); >> #endif >> diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c >> index 359b2bc888cf..2ac33d32edc2 100644 >> --- a/net/tipc/name_table.c >> +++ b/net/tipc/name_table.c >> @@ -729,6 +729,7 @@ struct publication *tipc_nametbl_publish(struct >> net *net, u32 type, u32 lower, >> struct tipc_net *tn = tipc_net(net); >> struct publication *p = NULL; >> struct sk_buff *skb = NULL; >> + u32 rc_dests; >> spin_lock_bh(&tn->nametbl_lock); >> @@ -743,12 +744,14 @@ struct publication >> *tipc_nametbl_publish(struct net *net, u32 type, u32 lower, >> nt->local_publ_count++; >> skb = tipc_named_publish(net, p); >> } >> + rc_dests = nt->rc_dests; >> exit: >> spin_unlock_bh(&tn->nametbl_lock); >> if (skb) >> - tipc_node_broadcast(net, skb); >> + tipc_node_broadcast(net, skb, rc_dests); >> return p; >> + >> } >> /** >> @@ -762,6 +765,7 @@ int tipc_nametbl_withdraw(struct net *net, u32 >> type, u32 lower, >> u32 self = tipc_own_addr(net); >> struct sk_buff *skb = NULL; >> struct publication *p; >> + u32 rc_dests; >> spin_lock_bh(&tn->nametbl_lock); >> @@ -775,10 +779,11 @@ int tipc_nametbl_withdraw(struct net *net, >> u32 type, u32 lower, >> pr_err("Failed to remove local publication {%u,%u,%u}/%u\n", >> type, lower, upper, key); >> } >> + rc_dests = nt->rc_dests; >> spin_unlock_bh(&tn->nametbl_lock); >> if (skb) { >> - tipc_node_broadcast(net, skb); >> + tipc_node_broadcast(net, skb, rc_dests); >> return 1; >> } >> return 0; >> diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h >> index 728bc7016c38..8064e1986e2c 100644 >> --- a/net/tipc/name_table.h >> +++ b/net/tipc/name_table.h >> @@ -106,6 +106,8 @@ struct name_table { >> struct list_head cluster_scope; >> rwlock_t cluster_scope_lock; >> u32 local_publ_count; >> + u32 rc_dests; >> + u32 snd_nxt; >> }; >> int tipc_nl_name_table_dump(struct sk_buff *skb, struct >> netlink_callback *cb); >> diff --git a/net/tipc/node.c b/net/tipc/node.c >> index a4c2816c3746..030a51c4d1fa 100644 >> --- a/net/tipc/node.c >> +++ b/net/tipc/node.c >> @@ -75,6 +75,8 @@ struct tipc_bclink_entry { >> struct sk_buff_head arrvq; >> struct sk_buff_head inputq2; >> struct sk_buff_head namedq; >> + u16 named_rcv_nxt; >> + bool named_open; >> }; >> /** >> @@ -396,10 +398,10 @@ static void tipc_node_write_unlock(struct >> tipc_node *n) >> write_unlock_bh(&n->lock); >> if (flags & TIPC_NOTIFY_NODE_DOWN) >> - tipc_publ_notify(net, publ_list, addr); >> + tipc_publ_notify(net, publ_list, addr, n->capabilities); >> if (flags & TIPC_NOTIFY_NODE_UP) >> - tipc_named_node_up(net, addr); >> + tipc_named_node_up(net, addr, n->capabilities); >> if (flags & TIPC_NOTIFY_LINK_UP) { >> tipc_mon_peer_up(net, addr, bearer_id); >> @@ -1483,6 +1485,7 @@ static void node_lost_contact(struct tipc_node *n, >> /* Clean up broadcast state */ >> tipc_bcast_remove_peer(n->net, n->bc_entry.link); >> + __skb_queue_purge(&n->bc_entry.namedq); >> /* Abort any ongoing link failover */ >> for (i = 0; i < MAX_BEARERS; i++) { >> @@ -1729,12 +1732,23 @@ int tipc_node_distr_xmit(struct net *net, >> struct sk_buff_head *xmitq) >> return 0; >> } >> -void tipc_node_broadcast(struct net *net, struct sk_buff *skb) >> +void tipc_node_broadcast(struct net *net, struct sk_buff *skb, int >> rc_dests) >> { >> + struct sk_buff_head xmitq; >> struct sk_buff *txskb; >> struct tipc_node *n; >> + u16 dummy; >> u32 dst; >> + /* Use broadcast if all nodes support it */ >> + if (!rc_dests && tipc_bcast_get_mode(net) != BCLINK_MODE_RCAST) { >> + __skb_queue_head_init(&xmitq); >> + __skb_queue_tail(&xmitq, skb); >> + tipc_bcast_xmit(net, &xmitq, &dummy); >> + return; >> + } >> + >> + /* Otherwise use legacy replicast method */ >> rcu_read_lock(); >> list_for_each_entry_rcu(n, tipc_nodes(net), list) { >> dst = n->addr; >> @@ -1749,7 +1763,6 @@ void tipc_node_broadcast(struct net *net, >> struct sk_buff *skb) >> tipc_node_xmit_skb(net, txskb, dst, 0); >> } >> rcu_read_unlock(); >> - >> kfree_skb(skb); >> } >> @@ -1844,7 +1857,9 @@ static void tipc_node_bc_rcv(struct net *net, >> struct sk_buff *skb, int bearer_id >> /* Handle NAME_DISTRIBUTOR messages sent from 1.7 nodes */ >> if (!skb_queue_empty(&n->bc_entry.namedq)) >> - tipc_named_rcv(net, &n->bc_entry.namedq); >> + tipc_named_rcv(net, &n->bc_entry.namedq, >> + &n->bc_entry.named_rcv_nxt, >> + &n->bc_entry.named_open); >> /* If reassembly or retransmission failure => reset all links >> to peer */ >> if (rc & TIPC_LINK_DOWN_EVT) >> @@ -2114,7 +2129,9 @@ void tipc_rcv(struct net *net, struct sk_buff >> *skb, struct tipc_bearer *b) >> tipc_node_link_down(n, bearer_id, false); >> if (unlikely(!skb_queue_empty(&n->bc_entry.namedq))) >> - tipc_named_rcv(net, &n->bc_entry.namedq); >> + tipc_named_rcv(net, &n->bc_entry.namedq, >> + &n->bc_entry.named_rcv_nxt, >> + &n->bc_entry.named_open); >> if (unlikely(!skb_queue_empty(&n->bc_entry.inputq1))) >> tipc_node_mcast_rcv(n); >> diff --git a/net/tipc/node.h b/net/tipc/node.h >> index a6803b449a2c..9f6f13f1604f 100644 >> --- a/net/tipc/node.h >> +++ b/net/tipc/node.h >> @@ -55,7 +55,8 @@ enum { >> TIPC_MCAST_RBCTL = (1 << 7), >> TIPC_GAP_ACK_BLOCK = (1 << 8), >> TIPC_TUNNEL_ENHANCED = (1 << 9), >> - TIPC_NAGLE = (1 << 10) >> + TIPC_NAGLE = (1 << 10), >> + TIPC_NAMED_BCAST = (1 << 11) >> }; >> #define TIPC_NODE_CAPABILITIES (TIPC_SYN_BIT | \ >> @@ -68,7 +69,8 @@ enum { >> TIPC_MCAST_RBCTL | \ >> TIPC_GAP_ACK_BLOCK | \ >> TIPC_TUNNEL_ENHANCED | \ >> - TIPC_NAGLE) >> + TIPC_NAGLE | \ >> + TIPC_NAMED_BCAST) >> #define INVALID_BEARER_ID -1 >> @@ -101,7 +103,7 @@ int tipc_node_xmit_skb(struct net *net, struct >> sk_buff *skb, u32 dest, >> u32 selector); >> void tipc_node_subscribe(struct net *net, struct list_head *subscr, >> u32 addr); >> void tipc_node_unsubscribe(struct net *net, struct list_head >> *subscr, u32 addr); >> -void tipc_node_broadcast(struct net *net, struct sk_buff *skb); >> +void tipc_node_broadcast(struct net *net, struct sk_buff *skb, int >> rc_dests); >> int tipc_node_add_conn(struct net *net, u32 dnode, u32 port, u32 >> peer_port); >> void tipc_node_remove_conn(struct net *net, u32 dnode, u32 port); >> int tipc_node_get_mtu(struct net *net, u32 addr, u32 sel, bool >> connected); > > > > _______________________________________________ > tipc-discussion mailing list > tipc-discussion@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/tipc-discussion > _______________________________________________ tipc-discussion mailing list tipc-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tipc-discussion _______________________________________________ tipc-discussion mailing list tipc-discussion@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tipc-discussion