^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) }