Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * net/tipc/monitor.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copyright (c) 2016, Ericsson AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * modification, are permitted provided that the following conditions are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * 1. Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *    notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * 2. Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *    notice, this list of conditions and the following disclaimer in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *    documentation and/or other materials provided with the distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * 3. Neither the names of the copyright holders nor the names of its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *    contributors may be used to endorse or promote products derived from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *    this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * Alternatively, this software may be distributed under the terms of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * GNU General Public License ("GPL") version 2 as published by the Free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include "addr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #include "monitor.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include "bearer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define MAX_MON_DOMAIN       64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define MON_TIMEOUT          120000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define MAX_PEER_DOWN_EVENTS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) /* struct tipc_mon_domain: domain record to be transferred between peers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * @len: actual size of domain record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  * @gen: current generation of sender's domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * @ack_gen: most recent generation of self's domain acked by peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * @member_cnt: number of domain member nodes described in this record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * @up_map: bit map indicating which of the members the sender considers up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * @members: identity of the domain members
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) struct tipc_mon_domain {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	u16 gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	u16 ack_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	u16 member_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	u64 up_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	u32 members[MAX_MON_DOMAIN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) /* struct tipc_peer: state of a peer node and its domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * @addr: tipc node identity of peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * @head_map: shows which other nodes currently consider peer 'up'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * @domain: most recent domain record from peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * @hash: position in hashed lookup list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * @list: position in linked list, in circular ascending order by 'addr'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * @applied: number of reported domain members applied on this monitor list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * @is_up: peer is up as seen from this node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * @is_head: peer is assigned domain head as seen from this node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * @is_local: peer is in local domain and should be continuously monitored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  * @down_cnt: - numbers of other peers which have reported this on lost
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) struct tipc_peer {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	struct tipc_mon_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	struct hlist_node hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	u8 applied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	u8 down_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	bool is_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	bool is_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	bool is_local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) struct tipc_monitor {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	struct hlist_head peers[NODE_HTABLE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	int peer_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct tipc_peer *self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	rwlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	struct tipc_mon_domain cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	u16 list_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	u16 dom_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	struct net *net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	struct timer_list timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	unsigned long timer_intv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct tipc_monitor *tipc_monitor(struct net *net, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	return tipc_net(net)->monitors[bearer_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) const int tipc_max_domain_size = sizeof(struct tipc_mon_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* dom_rec_len(): actual length of domain record for transport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static int dom_rec_len(struct tipc_mon_domain *dom, u16 mcnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	return ((void *)&dom->members - (void *)dom) + (mcnt * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* dom_size() : calculate size of own domain based on number of peers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int dom_size(int peers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	while ((i * i) < peers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	return i < MAX_MON_DOMAIN ? i : MAX_MON_DOMAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void map_set(u64 *up_map, int i, unsigned int v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	*up_map &= ~(1ULL << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	*up_map |= ((u64)v << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int map_get(u64 up_map, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return (up_map & (1 << i)) >> i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static struct tipc_peer *peer_prev(struct tipc_peer *peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	return list_last_entry(&peer->list, struct tipc_peer, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static struct tipc_peer *peer_nxt(struct tipc_peer *peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	return list_first_entry(&peer->list, struct tipc_peer, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static struct tipc_peer *peer_head(struct tipc_peer *peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	while (!peer->is_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		peer = peer_prev(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	return peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static struct tipc_peer *get_peer(struct tipc_monitor *mon, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	struct tipc_peer *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	unsigned int thash = tipc_hashfn(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	hlist_for_each_entry(peer, &mon->peers[thash], hash) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		if (peer->addr == addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			return peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static struct tipc_peer *get_self(struct net *net, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	return mon->self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static inline bool tipc_mon_is_active(struct net *net, struct tipc_monitor *mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	struct tipc_net *tn = tipc_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	return mon->peer_cnt > tn->mon_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* mon_identify_lost_members() : - identify amd mark potentially lost members
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void mon_identify_lost_members(struct tipc_peer *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 				      struct tipc_mon_domain *dom_bef,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 				      int applied_bef)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	struct tipc_peer *member = peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	struct tipc_mon_domain *dom_aft = peer->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	int applied_aft = peer->applied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	for (i = 0; i < applied_bef; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		member = peer_nxt(member);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 		/* Do nothing if self or peer already see member as down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		if (!member->is_up || !map_get(dom_bef->up_map, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		/* Loss of local node must be detected by active probing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		if (member->is_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		/* Start probing if member was removed from applied domain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		if (!applied_aft || (applied_aft < i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 			member->down_cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		/* Member loss is confirmed if it is still in applied domain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		if (!map_get(dom_aft->up_map, i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			member->down_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* mon_apply_domain() : match a peer's domain record against monitor list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static void mon_apply_domain(struct tipc_monitor *mon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			     struct tipc_peer *peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	struct tipc_mon_domain *dom = peer->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	struct tipc_peer *member;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	u32 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	if (!dom || !peer->is_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	/* Scan across domain members and match against monitor list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	peer->applied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	member = peer_nxt(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	for (i = 0; i < dom->member_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		addr = dom->members[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		if (addr != member->addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		peer->applied++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		member = peer_nxt(member);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /* mon_update_local_domain() : update after peer addition/removal/up/down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static void mon_update_local_domain(struct tipc_monitor *mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	struct tipc_peer *self = mon->self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	struct tipc_mon_domain *cache = &mon->cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	struct tipc_mon_domain *dom = self->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	struct tipc_peer *peer = self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	u64 prev_up_map = dom->up_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	u16 member_cnt, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	bool diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	/* Update local domain size based on current size of cluster */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	member_cnt = dom_size(mon->peer_cnt) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	self->applied = member_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	/* Update native and cached outgoing local domain records */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	dom->len = dom_rec_len(dom, member_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	diff = dom->member_cnt != member_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	dom->member_cnt = member_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	for (i = 0; i < member_cnt; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		peer = peer_nxt(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		diff |= dom->members[i] != peer->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		dom->members[i] = peer->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		map_set(&dom->up_map, i, peer->is_up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		cache->members[i] = htonl(peer->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	diff |= dom->up_map != prev_up_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	if (!diff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	dom->gen = ++mon->dom_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	cache->len = htons(dom->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	cache->gen = htons(dom->gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	cache->member_cnt = htons(member_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	cache->up_map = cpu_to_be64(dom->up_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	mon_apply_domain(mon, self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* mon_update_neighbors() : update preceding neighbors of added/removed peer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static void mon_update_neighbors(struct tipc_monitor *mon,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 				 struct tipc_peer *peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	int dz, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	dz = dom_size(mon->peer_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	for (i = 0; i < dz; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		mon_apply_domain(mon, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 		peer = peer_prev(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /* mon_assign_roles() : reassign peer roles after a network change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  * The monitor list is consistent at this stage; i.e., each peer is monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  * a set of domain members as matched between domain record and the monitor list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static void mon_assign_roles(struct tipc_monitor *mon, struct tipc_peer *head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	struct tipc_peer *peer = peer_nxt(head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	struct tipc_peer *self = mon->self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	for (; peer != self; peer = peer_nxt(peer)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 		peer->is_local = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		/* Update domain member */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		if (i++ < head->applied) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 			peer->is_head = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 			if (head == self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 				peer->is_local = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 		/* Assign next domain head */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		if (!peer->is_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		if (peer->is_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		head = peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		head->is_head = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	mon->list_gen++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) void tipc_mon_remove_peer(struct net *net, u32 addr, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	struct tipc_peer *self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	struct tipc_peer *peer, *prev, *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	if (!mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	self = get_self(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	peer = get_peer(mon, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	if (!peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	prev = peer_prev(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	list_del(&peer->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	hlist_del(&peer->hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	kfree(peer->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	kfree(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	mon->peer_cnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	head = peer_head(prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	if (head == self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		mon_update_local_domain(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	mon_update_neighbors(mon, prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	/* Revert to full-mesh monitoring if we reach threshold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	if (!tipc_mon_is_active(net, mon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		list_for_each_entry(peer, &self->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 			kfree(peer->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			peer->domain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 			peer->applied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	mon_assign_roles(mon, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static bool tipc_mon_add_peer(struct tipc_monitor *mon, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 			      struct tipc_peer **peer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	struct tipc_peer *self = mon->self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	struct tipc_peer *cur, *prev, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	p = kzalloc(sizeof(*p), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	*peer = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	p->addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	/* Add new peer to lookup list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	INIT_LIST_HEAD(&p->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	hlist_add_head(&p->hash, &mon->peers[tipc_hashfn(addr)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	/* Sort new peer into iterator list, in ascending circular order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	prev = self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	list_for_each_entry(cur, &self->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		if ((addr > prev->addr) && (addr < cur->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 		if (((addr < cur->addr) || (addr > prev->addr)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		    (prev->addr > cur->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 		prev = cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 	list_add_tail(&p->list, &cur->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	mon->peer_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	mon_update_neighbors(mon, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) void tipc_mon_peer_up(struct net *net, u32 addr, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 	struct tipc_peer *self = get_self(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	struct tipc_peer *peer, *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 	peer = get_peer(mon, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 	if (!peer && !tipc_mon_add_peer(mon, addr, &peer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 	peer->is_up = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	head = peer_head(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 	if (head == self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 		mon_update_local_domain(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	mon_assign_roles(mon, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) void tipc_mon_peer_down(struct net *net, u32 addr, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	struct tipc_peer *self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	struct tipc_peer *peer, *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	struct tipc_mon_domain *dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	int applied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	if (!mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	self = get_self(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	peer = get_peer(mon, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 	if (!peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 		pr_warn("Mon: unknown link %x/%u DOWN\n", addr, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) 	applied = peer->applied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 	peer->applied = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) 	dom = peer->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) 	peer->domain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) 	if (peer->is_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 		mon_identify_lost_members(peer, dom, applied);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) 	kfree(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 	peer->is_up = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) 	peer->is_head = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) 	peer->is_local = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) 	peer->down_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 	head = peer_head(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	if (head == self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 		mon_update_local_domain(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	mon_assign_roles(mon, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 	write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) /* tipc_mon_rcv - process monitor domain event message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) void tipc_mon_rcv(struct net *net, void *data, u16 dlen, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 		  struct tipc_mon_state *state, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) 	struct tipc_mon_domain *arrv_dom = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) 	struct tipc_mon_domain dom_bef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 	struct tipc_mon_domain *dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 	struct tipc_peer *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) 	u16 new_member_cnt = ntohs(arrv_dom->member_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) 	int new_dlen = dom_rec_len(arrv_dom, new_member_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) 	u16 new_gen = ntohs(arrv_dom->gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 	u16 acked_gen = ntohs(arrv_dom->ack_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) 	bool probing = state->probing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) 	int i, applied_bef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	state->probing = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	/* Sanity check received domain record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 	if (new_member_cnt > MAX_MON_DOMAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 	if (dlen < dom_rec_len(arrv_dom, 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	if (dlen != dom_rec_len(arrv_dom, new_member_cnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	if ((dlen < new_dlen) || ntohs(arrv_dom->len) != new_dlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	/* Synch generation numbers with peer if link just came up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 	if (!state->synched) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 		state->peer_gen = new_gen - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		state->acked_gen = acked_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 		state->synched = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 	if (more(acked_gen, state->acked_gen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		state->acked_gen = acked_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 	/* Drop duplicate unless we are waiting for a probe response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 	if (!more(new_gen, state->peer_gen) && !probing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	peer = get_peer(mon, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) 	if (!peer || !peer->is_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) 	/* Peer is confirmed, stop any ongoing probing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 	peer->down_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) 	/* Task is done for duplicate record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) 	if (!more(new_gen, state->peer_gen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 		goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) 	state->peer_gen = new_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) 	/* Cache current domain record for later use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) 	dom_bef.member_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	dom = peer->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	if (dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 		memcpy(&dom_bef, dom, dom->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 	/* Transform and store received domain record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) 	if (!dom || (dom->len < new_dlen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 		kfree(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) 		dom = kmalloc(new_dlen, GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) 		peer->domain = dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) 		if (!dom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) 			goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) 	dom->len = new_dlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) 	dom->gen = new_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) 	dom->member_cnt = new_member_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) 	dom->up_map = be64_to_cpu(arrv_dom->up_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 	for (i = 0; i < new_member_cnt; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) 		dom->members[i] = ntohl(arrv_dom->members[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) 	/* Update peers affected by this domain record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	applied_bef = peer->applied;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	mon_apply_domain(mon, peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	mon_identify_lost_members(peer, &dom_bef, applied_bef);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 	mon_assign_roles(mon, peer_head(peer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 	write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) void tipc_mon_prep(struct net *net, void *data, int *dlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 		   struct tipc_mon_state *state, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 	struct tipc_mon_domain *dom = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 	u16 gen = mon->dom_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 	u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 	/* Send invalid record if not active */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	if (!tipc_mon_is_active(net, mon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 		dom->len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 	/* Send only a dummy record with ack if peer has acked our last sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	if (likely(state->acked_gen == gen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 		len = dom_rec_len(dom, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 		*dlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 		dom->len = htons(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 		dom->gen = htons(gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 		dom->ack_gen = htons(state->peer_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		dom->member_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 	/* Send the full record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	read_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	len = ntohs(mon->cache.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	*dlen = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	memcpy(data, &mon->cache, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	read_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	dom->ack_gen = htons(state->peer_gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) void tipc_mon_get_state(struct net *net, u32 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 			struct tipc_mon_state *state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 			int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 	struct tipc_peer *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 	if (!tipc_mon_is_active(net, mon)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 		state->probing = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 		state->monitoring = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 	/* Used cached state if table has not changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 	if (!state->probing &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 	    (state->list_gen == mon->list_gen) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	    (state->acked_gen == mon->dom_gen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	read_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	peer = get_peer(mon, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 	if (peer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 		state->probing = state->acked_gen != mon->dom_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 		state->probing |= peer->down_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 		state->reset |= peer->down_cnt >= MAX_PEER_DOWN_EVENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 		state->monitoring = peer->is_local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 		state->monitoring |= peer->is_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 		state->list_gen = mon->list_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 	read_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static void mon_timeout(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 	struct tipc_monitor *mon = from_timer(mon, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 	struct tipc_peer *self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	int best_member_cnt = dom_size(mon->peer_cnt) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) 	write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 	self = mon->self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) 	if (self && (best_member_cnt != self->applied)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) 		mon_update_local_domain(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) 		mon_assign_roles(mon, self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) 	write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) 	mod_timer(&mon->timer, jiffies + mon->timer_intv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) int tipc_mon_create(struct net *net, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	struct tipc_net *tn = tipc_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	struct tipc_monitor *mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	struct tipc_peer *self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	struct tipc_mon_domain *dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	if (tn->monitors[bearer_id])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	mon = kzalloc(sizeof(*mon), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	self = kzalloc(sizeof(*self), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 	dom = kzalloc(sizeof(*dom), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	if (!mon || !self || !dom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 		kfree(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 		kfree(self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 		kfree(dom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	tn->monitors[bearer_id] = mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	rwlock_init(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 	mon->net = net;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	mon->peer_cnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 	mon->self = self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 	self->domain = dom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 	self->addr = tipc_own_addr(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 	self->is_up = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 	self->is_head = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 	INIT_LIST_HEAD(&self->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 	timer_setup(&mon->timer, mon_timeout, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 	mon->timer_intv = msecs_to_jiffies(MON_TIMEOUT + (tn->random & 0xffff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 	mod_timer(&mon->timer, jiffies + mon->timer_intv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) void tipc_mon_delete(struct net *net, int bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 	struct tipc_net *tn = tipc_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 	struct tipc_peer *self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 	struct tipc_peer *peer, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 	if (!mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 	self = get_self(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 	write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 	tn->monitors[bearer_id] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 	list_for_each_entry_safe(peer, tmp, &self->list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 		list_del(&peer->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 		hlist_del(&peer->hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 		kfree(peer->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 		kfree(peer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 	mon->self = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 	write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 	del_timer_sync(&mon->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 	kfree(self->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 	kfree(self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 	kfree(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) void tipc_mon_reinit_self(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 	struct tipc_monitor *mon;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 	int bearer_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 	for (bearer_id = 0; bearer_id < MAX_BEARERS; bearer_id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 		mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 		if (!mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 		write_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 		mon->self->addr = tipc_own_addr(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 		write_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) int tipc_nl_monitor_set_threshold(struct net *net, u32 cluster_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) 	struct tipc_net *tn = tipc_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) 	if (cluster_size > TIPC_CLUSTER_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) 	tn->mon_threshold = cluster_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int tipc_nl_monitor_get_threshold(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	struct tipc_net *tn = tipc_net(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	return tn->mon_threshold;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) static int __tipc_nl_add_monitor_peer(struct tipc_peer *peer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 				      struct tipc_nl_msg *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 	struct tipc_mon_domain *dom = peer->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	struct nlattr *attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 			  NLM_F_MULTI, TIPC_NL_MON_PEER_GET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_MON_PEER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	if (!attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 		goto msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEER_ADDR, peer->addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 		goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEER_APPLIED, peer->applied))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) 	if (peer->is_up)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 		if (nla_put_flag(msg->skb, TIPC_NLA_MON_PEER_UP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 	if (peer->is_local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		if (nla_put_flag(msg->skb, TIPC_NLA_MON_PEER_LOCAL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 	if (peer->is_head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 		if (nla_put_flag(msg->skb, TIPC_NLA_MON_PEER_HEAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 	if (dom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 		if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEER_DOMGEN, dom->gen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 		if (nla_put_u64_64bit(msg->skb, TIPC_NLA_MON_PEER_UPMAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 				      dom->up_map, TIPC_NLA_MON_PEER_PAD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 		if (nla_put(msg->skb, TIPC_NLA_MON_PEER_MEMBERS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 			    dom->member_cnt * sizeof(u32), &dom->members))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	nla_nest_end(msg->skb, attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	genlmsg_end(msg->skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) attr_msg_full:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	nla_nest_cancel(msg->skb, attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) msg_full:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	genlmsg_cancel(msg->skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 	return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) int tipc_nl_add_monitor_peer(struct net *net, struct tipc_nl_msg *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 			     u32 bearer_id, u32 *prev_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	struct tipc_peer *peer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	if (!mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 	read_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 	peer = mon->self;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		if (*prev_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 			if (peer->addr == *prev_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 				*prev_node = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 		if (__tipc_nl_add_monitor_peer(peer, msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 			*prev_node = peer->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 			read_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 			return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 	} while ((peer = peer_nxt(peer)) != mon->self);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 	read_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) int __tipc_nl_add_monitor(struct net *net, struct tipc_nl_msg *msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 			  u32 bearer_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 	struct tipc_monitor *mon = tipc_monitor(net, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 	char bearer_name[TIPC_MAX_BEARER_NAME];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	struct nlattr *attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	void *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 	ret = tipc_bearer_get_name(net, bearer_name, bearer_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	if (ret || !mon)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) 	hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 			  NLM_F_MULTI, TIPC_NL_MON_GET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 	if (!hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 		return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 	attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_MON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 	if (!attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 		goto msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 	read_lock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	if (nla_put_u32(msg->skb, TIPC_NLA_MON_REF, bearer_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) 		goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 	if (tipc_mon_is_active(net, mon))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 		if (nla_put_flag(msg->skb, TIPC_NLA_MON_ACTIVE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 			goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 	if (nla_put_string(msg->skb, TIPC_NLA_MON_BEARER_NAME, bearer_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 		goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) 	if (nla_put_u32(msg->skb, TIPC_NLA_MON_PEERCNT, mon->peer_cnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 	if (nla_put_u32(msg->skb, TIPC_NLA_MON_LISTGEN, mon->list_gen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 		goto attr_msg_full;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 	read_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 	nla_nest_end(msg->skb, attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 	genlmsg_end(msg->skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) attr_msg_full:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 	read_unlock_bh(&mon->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 	nla_nest_cancel(msg->skb, attrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) msg_full:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 	genlmsg_cancel(msg->skb, hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 	return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }