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