> -----Original Message-----
> From: Parthasarathy Bhuvaragan
> Sent: Monday, 18 April, 2016 09:30
> To: Jon Maloy; tipc-discussion@lists.sourceforge.net; Ying Xue; Richard Alpe
> Cc: ma...@donjonn.com
> Subject: Re: [PATCH net-next v2 1/1] tipc: add neighbor monitoring framework
> 
> Hi Jon,
> 

[...]

> > +   u16 dom_gen;
> > +   bool disabled;
> mon_breakpoint is defined in struct tipc_net, whereas the configuration
> option disabled is defined in struct tipc_monitor and tied to
> a bearer.
> I think this should belongs to struct tipc_net, as all the bearers have
> the same supervision algorithm.

No.  Each monitor list belongs to a bearer, and is disabled (and re-enabled) 
along with that bearer.
It is fully normal to disable one bearer and monitor list, while leaving the 
other one active.

///jon


> > +   struct net *net;
> > +};
> > +
> > +static struct tipc_monitor *tipc_monitor(struct net *net, int bearer_id)
> > +{
> > +   return tipc_net(net)->monitors[bearer_id];
> > +}
> > +
> > +const int tipc_max_domain_size = sizeof(struct tipc_mon_domain);
> > +
> > +/* dom_rec_len(): actual size of domain record for transport
> > + */
> > +static int dom_rec_len(struct tipc_mon_domain *dom, u16 mcnt)
> > +{
> > +   return ((void *)&dom->members - (void *)dom) + (mcnt * sizeof(u32));
> > +}
> > +
> > +/* dom_size() : calculate size of own domain based on number of peers
> > + */
> > +static int dom_size(int peers)
> > +{
> > +   int i = 0;
> > +
> > +   while ((i * i) < peers)
> > +           i++;
> > +   return i < TIPC_MAX_MON_DOMAIN ? i : TIPC_MAX_MON_DOMAIN;
> > +}
> > +
> > +static void map_set(u64 *up_map, int i, unsigned int v)
> > +{
> > +   *up_map &= ~(1 << i);
> > +   *up_map |= (v << i);
> > +}
> > +
> > +static int map_get(u64 up_map, int i)
> > +{
> > +   return (up_map & (1 << i)) >> i;
> > +}
> > +
> > +static struct tipc_peer *peer_prev(struct tipc_peer *peer)
> > +{
> > +   return list_last_entry(&peer->list, struct tipc_peer, list);
> > +}
> > +
> > +static struct tipc_peer *peer_nxt(struct tipc_peer *peer)
> > +{
> > +   return list_first_entry(&peer->list, struct tipc_peer, list);
> > +}
> > +
> > +static struct tipc_peer *peer_head(struct tipc_peer *peer)
> > +{
> > +   while (!peer->is_head)
> > +           peer = peer_prev(peer);
> > +   return peer;
> > +}
> > +
> > +static struct tipc_peer *get_peer(struct tipc_monitor *mon, u32 addr)
> > +{
> > +   struct tipc_peer *peer;
> > +   unsigned int thash = tipc_hashfn(addr);
> > +
> > +   hlist_for_each_entry(peer, &mon->peers[thash], hash) {
> > +           if (peer->addr == addr)
> > +                   return peer;
> > +   }
> > +   return NULL;
> > +}
> > +
> > +static struct tipc_peer *get_self(struct net *net, int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +
> > +   return mon->self;
> > +}
> > +
> > +/* mon_match_domain() : match a peer's domain record against monitor list
> > + */
> > +static void mon_match_domain(struct tipc_monitor *mon,
> > +                        struct tipc_peer *peer)
> > +{
> > +   struct tipc_mon_domain *dom = peer->domain;
> > +   struct tipc_peer *member;
> > +   u64 prev_map;
> > +   u32 addr;
> > +   int up, i;
> > +
> > +   if (!dom || !peer->is_up)
> > +           return;
> > +
> > +   /* Scan across domain members and match against monitor list */
> > +   peer->monitoring = 0;
> > +   member = peer_nxt(peer);
> > +   for (i = 0; i < dom->member_cnt; i++) {
> > +           addr = dom->members[i];
> > +           if (addr != member->addr)
> > +                   return;
> > +           if (addr == tipc_own_addr(mon->net))
> > +                   return;
> > +           peer->monitoring++;
> > +           prev_map = member->head_map;
> > +
> > +           /* Set peer's up/down status for this member in its head map */
> > +           up = map_get(dom->up_map, i);
> > +           map_set(&member->head_map, i, up);
> > +
> > +           /* Start confirmation probing if status went up -> down */
> > +           if (member->is_up && !up && (member->head_map !=
> prev_map))
> > +                   member->confirm = true;
> > +           member = peer_nxt(member);
> > +   }
> > +}
> > +
> > +/* mon_update_local_domain() : update after peer
> addition/removal/up/down
> > + */
> > +static void mon_update_local_domain(struct tipc_monitor *mon)
> > +{
> > +   struct tipc_peer *self = mon->self;
> > +   struct tipc_mon_domain *cache = &mon->cache;
> > +   struct tipc_mon_domain *dom = self->domain;
> > +   struct tipc_peer *peer = self;
> > +   int member_cnt, i;
> > +
> > +   /* Update local domain size based on current size of cluster */
> > +   member_cnt = dom_size(mon->peer_cnt) - 1;
> > +   self->monitoring = member_cnt;
> > +
> > +   /* Update native and cached outgoing local domain records */
> > +   dom->len = dom_rec_len(dom, member_cnt);
> > +   dom->gen = ++mon->dom_gen;
> > +   dom->member_cnt = member_cnt;
> > +   for (i = 0; i < member_cnt; i++) {
> > +           peer = peer_nxt(peer);
> > +           dom->members[i] = peer->addr;
> > +           map_set(&dom->up_map, i, peer->is_up);
> > +           cache->members[i] = htonl(peer->addr);
> > +   }
> > +   cache->len = htons(dom->len);
> > +   cache->gen = htons(dom->gen);
> > +   cache->member_cnt = htons(member_cnt);
> > +   cache->up_map = cpu_to_be64(dom->up_map);
> > +   mon_match_domain(mon, self);
> > +}
> > +
> > +/* mon_update_neighbors() : update neighbors around an added/removed
> peer
> > + */
> > +static void mon_update_neighbors(struct tipc_monitor *mon,
> > +                            struct tipc_peer *peer)
> > +{
> > +   int dz, i;
> > +
> > +   dz = dom_size(mon->peer_cnt);
> > +   for (i = 0; i < dz; i++) {
> > +           peer->head_map = 0;
> > +           peer = peer_nxt(peer);
> > +   }
> > +   for (i = 0; i < (dz * 2); i++) {
> > +           mon_match_domain(mon, peer);
> > +           peer = peer_prev(peer);
> > +   }
> > +}
> > +
> > +/* mon_assign_roles() : reassign peer roles after a network change
> > + * The monitor list is consistent at this stage; i.e., each peer is 
> > monitoring
> > + * a set of domain members as matched beween domain record and the
> monitor list
> > + */
> > +static void mon_assign_roles(struct tipc_monitor *mon, struct tipc_peer
> *head)
> > +{
> > +   struct tipc_peer *peer = peer_nxt(head);
> > +   struct tipc_peer *self = mon->self;
> > +   int i = 0;
> > +
> > +   for (; peer != self; peer = peer_nxt(peer)) {
> > +           peer->is_local = false;
> > +
> > +           /* Update domain member */
> > +           if (i++ < head->monitoring) {
> > +                   peer->is_head = false;
> > +                   if (head == self)
> > +                           peer->is_local = true;
> > +                   continue;
> > +           }
> > +           /* Assign next domain head */
> > +           if (!peer->is_up)
> > +                   continue;
> > +           if (peer->is_head)
> > +                   break;
> > +           head = peer;
> > +           head->is_head = true;
> > +           i = 0;
> > +   }
> > +   mon->list_gen++;
> > +}
> > +
> > +void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_peer *self = get_self(net, bearer_id);
> > +   struct tipc_peer *peer, *prev, *head;
> > +
> > +   write_lock_bh(&mon->lock);
> > +   peer = get_peer(mon, addr);
> > +   if (!peer)
> > +           goto exit;
> > +   prev = peer_prev(peer);
> > +   list_del(&peer->list);
> > +   hlist_del(&peer->hash);
> > +   kfree(peer->domain);
> > +   kfree(peer);
> > +   mon->peer_cnt--;
> > +   head = peer_head(prev);
> > +   if (head == self)
> > +           mon_update_local_domain(mon);
> > +   mon_update_neighbors(mon, prev);
> > +   mon_assign_roles(mon, head);
> > +exit:
> > +   write_unlock_bh(&mon->lock);
> > +}
> > +
> > +static bool tipc_mon_add_peer(struct tipc_monitor *mon, u32 addr,
> > +                         struct tipc_peer **peer)
> > +{
> > +   struct tipc_peer *self = mon->self;
> > +   struct tipc_peer *cur, *prev, *p;
> > +
> > +   p = kzalloc(sizeof(*p), GFP_ATOMIC);
> > +   *peer = p;
> > +   if (!p)
> > +           return false;
> > +   p->addr = addr;
> > +
> > +   /* Add new peer to lookup list */
> > +   INIT_LIST_HEAD(&p->list);
> > +   hlist_add_head(&p->hash, &mon->peers[tipc_hashfn(addr)]);
> > +
> > +   /* Sort new peer into iterator list, in ascending circular order */
> > +   prev = self;
> > +   list_for_each_entry(cur, &self->list, list) {
> > +           if ((addr > prev->addr) && (addr < cur->addr))
> > +                   break;
> > +           if (((addr < cur->addr) || (addr > prev->addr)) &&
> > +               (prev->addr > cur->addr))
> > +                   break;
> > +           prev = cur;
> > +   }
> > +   list_add_tail(&p->list, &cur->list);
> > +   mon->peer_cnt++;
> > +   mon_update_neighbors(mon, p);
> > +   return true;
> > +}
> > +
> > +void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_peer *self = get_self(net, bearer_id);
> > +   struct tipc_peer *peer, *head;
> > +
> > +   write_lock_bh(&mon->lock);
> > +   peer = get_peer(mon, addr);
> > +   if (!peer && !tipc_mon_add_peer(mon, addr, &peer))
> > +           goto exit;
> > +   peer->is_up = true;
> > +   head = peer_head(peer);
> > +   if (head == self)
> > +           mon_update_local_domain(mon);
> > +   mon_assign_roles(mon, head);
> > +exit:
> > +   write_unlock_bh(&mon->lock);
> > +}
> > +
> > +void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_peer *self = get_self(net, bearer_id);
> > +   struct tipc_peer *peer, *member, *head;
> > +   int i = 0;
> > +
> > +   write_lock_bh(&mon->lock);
> > +   peer = get_peer(mon, addr);
> > +   if (!peer) {
> > +           pr_warn("Mon: unknown link %x/%u DOWN\n", addr,
> bearer_id);
> > +           goto exit;
> > +   }
> > +   /* Update domain members' head_map field */
> > +   if (peer->domain) {
> > +           peer->domain->up_map = 0;
> > +           mon_match_domain(mon, peer);
> > +   }
> > +   /* Suppress member probing if peer was not domain head */
> > +   member = peer_nxt(peer);
> > +   while (!peer->is_head && (i++ < peer->monitoring)) {
> > +           member->confirm = false;
> > +           member = peer_nxt(member);
> > +   }
> > +   peer->is_up = false;
> > +   peer->is_head = false;
> > +   peer->is_local = false;
> > +   peer->confirm = false;
> > +   peer->monitoring = 0;
> > +   kfree(peer->domain);
> > +   peer->domain = NULL;
> > +   head = peer_head(peer);
> > +   if (head == self)
> > +           mon_update_local_domain(mon);
> > +   mon_assign_roles(mon, head);
> > +exit:
> > +   write_unlock_bh(&mon->lock);
> > +}
> > +
> > +/* tipc_mon_rcv - process monitor domain event message
> > + */
> > +void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr,
> > +             struct tipc_mon_state *state, int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_mon_domain *ndom = data;
> > +   u16 nmember_cnt = ntohs(ndom->member_cnt);
> > +   int ndlen = dom_rec_len(ndom, nmember_cnt);
> > +   u16 ndgen = ntohs(ndom->gen);
> > +   struct tipc_mon_domain *dom;
> > +   struct tipc_peer *peer;
> > +   int i;
> > +
> > +   if (!dlen)
> > +           return;
> > +
> > +   if ((dlen != ntohs(ndom->len)) || (dlen != ndlen)) {
> > +           pr_warn_ratelimited("Received illegal domain record");
> > +           return;
> > +   }
> > +   state->ack_gen = ntohs(ndom->ack_gen);
> > +
> > +   /* Ignore if this generation already received */
> > +   if (!more(ndgen, state->peer_gen) && !state->probed)
> > +           return;
> > +   state->probed = 0;
> > +
> > +   write_lock_bh(&mon->lock);
> > +   peer = get_peer(mon, addr);
> > +   if (!peer)
> > +           goto exit;
> > +   if (!more(ndgen, state->peer_gen))
> > +           goto exit;
> > +   state->peer_gen = ndgen;
> > +   if (!peer->is_up)
> > +           goto exit;
> > +
> > +   /* Transform and store received domain record */
> > +   dom = peer->domain;
> > +   if (!dom || (dom->len < ndlen)) {
> > +           kfree(dom);
> > +           dom = kmalloc(ndlen, GFP_ATOMIC);
> > +           peer->domain = dom;
> > +           if (!dom)
> > +                   goto exit;
> > +   }
> > +   dom->len = ndlen;
> > +   dom->gen = ndgen;
> > +   dom->member_cnt = nmember_cnt;
> > +   dom->up_map = be64_to_cpu(ndom->up_map);
> > +   for (i = 0; i < nmember_cnt; i++)
> > +           dom->members[i] = ntohl(ndom->members[i]);
> > +
> > +   /* Update peers affected by this domain record */
> > +   mon_match_domain(mon, peer);
> > +   peer->confirm = 0;
> > +   mon_assign_roles(mon, peer_head(peer));
> > +exit:
> > +   write_unlock_bh(&mon->lock);
> > +}
> > +
> > +void tipc_mon_prep(struct net *net, void *data, int *dlen,
> > +              struct tipc_mon_state *state, int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_mon_domain *dom = data;
> > +   u16 gen = state->gen;
> > +
> > +   if (mon->peer_cnt < tipc_net(net)->mon_breakpoint) {
> > +           *dlen = 0;
> > +           return;
> > +   }
> > +   if (!less(state->ack_gen, gen) || mon->disabled) {
> > +           *dlen = dom_rec_len(dom, 0);
> > +           dom->len = htons(dom_rec_len(dom, 0));
> > +           dom->gen = htons(gen);
> > +           dom->ack_gen = htons(state->peer_gen);
> > +           dom->member_cnt = 0;
> > +           return;
> > +   }
> > +   read_lock_bh(&mon->lock);
> > +   *dlen = ntohs(mon->cache.len);
> > +   memcpy(data, &mon->cache, *dlen);
> > +   read_unlock_bh(&mon->lock);
> > +   dom->ack_gen = htons(state->peer_gen);
> > +}
> > +
> > +bool tipc_mon_is_probed(struct net *net, u32 addr,
> > +                   struct tipc_mon_state *state,
> > +                   int bearer_id)
> > +{
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_peer *peer;
> > +
> > +   if (mon->disabled)
> > +           return false;
> > +
> > +   if (!state->probed &&
> > +       !less(state->list_gen, mon->list_gen) &&
> > +       !less(state->ack_gen, state->gen))
> > +           return false;
> > +
> > +   read_lock_bh(&mon->lock);
> > +   peer = get_peer(mon, addr);
> > +   if (peer) {
> > +           state->probed = less(state->gen, mon->dom_gen);
> > +           state->probed |= less(state->ack_gen, state->gen);
> > +           state->probed |= peer->confirm;
> > +           peer->confirm = 0;
> > +           state->monitored = peer->is_local;
> > +           state->monitored |= peer->is_head;
> > +           state->monitored |= !peer->head_map;
> > +           state->list_gen = mon->list_gen;
> > +           state->gen = mon->dom_gen;
> > +   }
> > +   read_unlock_bh(&mon->lock);
> > +   return state->probed || state->monitored;
> > +}
> > +
> > +int tipc_mon_create(struct net *net, int bearer_id)
> > +{
> > +   struct tipc_net *tn = tipc_net(net);
> > +   struct tipc_monitor *mon;
> > +   struct tipc_peer *self;
> > +   struct tipc_mon_domain *dom;
> > +
> > +   if (tn->monitors[bearer_id])
> > +           return 0;
> > +
> > +   mon = kzalloc(sizeof(*mon), GFP_ATOMIC);
> > +   self = kzalloc(sizeof(*self), GFP_ATOMIC);
> > +   dom = kzalloc(sizeof(*dom), GFP_ATOMIC);
> > +   if (!mon || !self || !dom) {
> > +           kfree(mon);
> > +           kfree(self);
> > +           kfree(dom);
> > +           return -ENOMEM;
> > +   }
> > +   tn->monitors[bearer_id] = mon;
> > +   rwlock_init(&mon->lock);
> > +   mon->net = net;
> > +   mon->peer_cnt = 1;
> > +   mon->self = self;
> > +   self->domain = dom;
> > +   self->addr = tipc_own_addr(net);
> > +   self->is_up = true;
> > +   self->is_head = true;
> > +   INIT_LIST_HEAD(&self->list);
> > +   return 0;
> > +}
> > +
> > +void tipc_mon_disable(struct net *net, int bearer_id)
> > +{
> > +   tipc_monitor(net, bearer_id)->disabled = true;
> > +}
> > +
> > +void tipc_mon_delete(struct net *net, int bearer_id)
> > +{
> > +   struct tipc_net *tn = tipc_net(net);
> > +   struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
> > +   struct tipc_peer *self = get_self(net, bearer_id);
> > +   struct tipc_peer *peer, *tmp;
> > +
> > +   write_lock_bh(&mon->lock);
> > +   tn->monitors[bearer_id] = NULL;
> > +   list_for_each_entry_safe(peer, tmp, &self->list, list) {
> > +           list_del(&peer->list);
> > +           hlist_del(&peer->hash);
> > +           kfree(peer->domain);
> > +           kfree(peer);
> > +   }
> > +   kfree(self->domain);
> > +   kfree(self);
> > +   write_unlock_bh(&mon->lock);
> > +   tn->monitors[bearer_id] = NULL;
> > +   kfree(mon);
> > +}
> > diff --git a/net/tipc/monitor.h b/net/tipc/monitor.h
> > new file mode 100644
> > index 0000000..7a25541
> > --- /dev/null
> > +++ b/net/tipc/monitor.h
> > @@ -0,0 +1,72 @@
> > +/*
> > + * net/tipc/monitor.h
> > + *
> > + * Copyright (c) 2015, Ericsson AB
> > + * All rights reserved.
> > + *
> > + * Redistribution and use in source and binary forms, with or without
> > + * modification, are permitted provided that the following conditions are 
> > met:
> > + *
> > + * 1. Redistributions of source code must retain the above copyright
> > + *    notice, this list of conditions and the following disclaimer.
> > + * 2. Redistributions in binary form must reproduce the above copyright
> > + *    notice, this list of conditions and the following disclaimer in the
> > + *    documentation and/or other materials provided with the distribution.
> > + * 3. Neither the names of the copyright holders nor the names of its
> > + *    contributors may be used to endorse or promote products derived from
> > + *    this software without specific prior written permission.
> > + *
> > + * Alternatively, this software may be distributed under the terms of the
> > + * GNU General Public License ("GPL") version 2 as published by the Free
> > + * Software Foundation.
> > + *
> > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> CONTRIBUTORS "AS IS"
> > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> LIMITED TO, THE
> > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> PARTICULAR PURPOSE
> > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> CONTRIBUTORS BE
> > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> PROCUREMENT OF
> > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
> WHETHER IN
> > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> OTHERWISE)
> > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
> ADVISED OF THE
> > + * POSSIBILITY OF SUCH DAMAGE.
> > + */
> > +
> > +#ifndef _TIPC_MONITOR_H
> > +#define _TIPC_MONITOR_H
> > +
> > +/* struct tipc_mon_state: link instance's cache of monitor list and domain
> state
> > + * @list_gen: current generation of this node's monitor list
> > + * @gen: current generation of this node's local domain
> > + * @peer_gen: most recent domain generation received from peer
> > + * @ack_gen: most recent generation of self's domain acked by peer
> > + * @monitored: peer endpoint should continuously monitored
> > + * @probed: peer endpoint should be temporarily probed for potential loss
> > + */
> > +struct tipc_mon_state {
> > +   u16 list_gen;
> > +   u16 gen;
> > +   u16 peer_gen;
> > +   u16 ack_gen;
> > +   bool monitored;
> > +   bool probed;
> > +};
> > +
> > +int tipc_mon_create(struct net *net, int bearer_id);
> > +void tipc_mon_disable(struct net *net, int bearer_id);
> > +void tipc_mon_delete(struct net *net, int bearer_id);
> > +
> > +void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id);
> > +void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id);
> > +void tipc_mon_prep(struct net *net, void *data, int *dlen,
> > +              struct tipc_mon_state *state, int bearer_id);
> > +void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr,
> > +             struct tipc_mon_state *state, int bearer_id);
> > +bool tipc_mon_is_probed(struct net *net, u32 addr,
> > +                   struct tipc_mon_state *state,
> > +                   int bearer_id);
> > +void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id);
> > +
> > +extern const int tipc_max_domain_size;
> > +#endif
> > diff --git a/net/tipc/node.c b/net/tipc/node.c
> > index 68d9f7b..43f2d78 100644
> > --- a/net/tipc/node.c
> > +++ b/net/tipc/node.c
> > @@ -40,6 +40,7 @@
> >  #include "name_distr.h"
> >  #include "socket.h"
> >  #include "bcast.h"
> > +#include "monitor.h"
> >  #include "discover.h"
> >  #include "netlink.h"
> >
> > @@ -191,16 +192,6 @@ int tipc_node_get_mtu(struct net *net, u32 addr, u32
> sel)
> >     tipc_node_put(n);
> >     return mtu;
> >  }
> > -/*
> > - * A trivial power-of-two bitmask technique is used for speed, since this
> > - * operation is done for every incoming TIPC packet. The number of hash 
> > table
> > - * entries has been chosen so that no hash chain exceeds 8 nodes and will
> > - * usually be much smaller (typically only a single node).
> > - */
> > -static unsigned int tipc_hashfn(u32 addr)
> > -{
> > -   return addr & (NODE_HTABLE_SIZE - 1);
> > -}
> >
> >  static void tipc_node_kref_release(struct kref *kref)
> >  {
> > @@ -265,6 +256,7 @@ static void tipc_node_write_unlock(struct tipc_node *n)
> >     u32 addr = 0;
> >     u32 flags = n->action_flags;
> >     u32 link_id = 0;
> > +   u32 bearer_id;
> >     struct list_head *publ_list;
> >
> >     if (likely(!flags)) {
> > @@ -274,6 +266,7 @@ static void tipc_node_write_unlock(struct tipc_node *n)
> >
> >     addr = n->addr;
> >     link_id = n->link_id;
> > +   bearer_id = link_id & 0xffff;
> >     publ_list = &n->publ_list;
> >
> >     n->action_flags &= ~(TIPC_NOTIFY_NODE_DOWN |
> TIPC_NOTIFY_NODE_UP |
> > @@ -287,13 +280,16 @@ static void tipc_node_write_unlock(struct tipc_node
> *n)
> >     if (flags & TIPC_NOTIFY_NODE_UP)
> >             tipc_named_node_up(net, addr);
> >
> > -   if (flags & TIPC_NOTIFY_LINK_UP)
> > +   if (flags & TIPC_NOTIFY_LINK_UP) {
> > +           tipc_mon_peer_up(net, addr, bearer_id);
> >             tipc_nametbl_publish(net, TIPC_LINK_STATE, addr, addr,
> >                                  TIPC_NODE_SCOPE, link_id, addr);
> > -
> > -   if (flags & TIPC_NOTIFY_LINK_DOWN)
> > +   }
> > +   if (flags & TIPC_NOTIFY_LINK_DOWN) {
> > +           tipc_mon_peer_down(net, addr, bearer_id);
> >             tipc_nametbl_withdraw(net, TIPC_LINK_STATE, addr,
> >                                   link_id, addr);
> > +   }
> >  }
> >
> >  struct tipc_node *tipc_node_create(struct net *net, u32 addr, u16 
> > capabilities)
> > @@ -674,6 +670,7 @@ static void tipc_node_link_down(struct tipc_node *n,
> int bearer_id, bool delete)
> >     struct tipc_link *l = le->link;
> >     struct tipc_media_addr *maddr;
> >     struct sk_buff_head xmitq;
> > +   int old_bearer_id = bearer_id;
> >
> >     if (!l)
> >             return;
> > @@ -693,6 +690,8 @@ static void tipc_node_link_down(struct tipc_node *n,
> int bearer_id, bool delete)
> >             tipc_link_fsm_evt(l, LINK_RESET_EVT);
> >     }
> >     tipc_node_write_unlock(n);
> > +   if (delete)
> > +           tipc_mon_remove_peer(n->net, n->addr, old_bearer_id);
> >     tipc_bearer_xmit(n->net, bearer_id, &xmitq, maddr);
> >     tipc_sk_rcv(n->net, &le->inputq);
> >  }


------------------------------------------------------------------------------
Find and fix application performance issues faster with Applications Manager
Applications Manager provides deep performance insights into multiple tiers of
your business applications. It resolves application problems quickly and
reduces your MTTR. Get your free trial!
https://ad.doubleclick.net/ddm/clk/302982198;130105516;z
_______________________________________________
tipc-discussion mailing list
tipc-discussion@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tipc-discussion

Reply via email to