xref: /openbmc/linux/net/tipc/name_distr.c (revision b97bf3fd8f6a16966d4f18983b2c40993ff937d4)
1*b97bf3fdSPer Liden /*
2*b97bf3fdSPer Liden  * net/tipc/name_distr.c: TIPC name distribution code
3*b97bf3fdSPer Liden  *
4*b97bf3fdSPer Liden  * Copyright (c) 2003-2005, Ericsson Research Canada
5*b97bf3fdSPer Liden  * Copyright (c) 2005, Wind River Systems
6*b97bf3fdSPer Liden  * Copyright (c) 2005-2006, Ericsson AB
7*b97bf3fdSPer Liden  * All rights reserved.
8*b97bf3fdSPer Liden  *
9*b97bf3fdSPer Liden  * Redistribution and use in source and binary forms, with or without
10*b97bf3fdSPer Liden  * modification, are permitted provided that the following conditions are met:
11*b97bf3fdSPer Liden  *
12*b97bf3fdSPer Liden  * Redistributions of source code must retain the above copyright notice, this
13*b97bf3fdSPer Liden  * list of conditions and the following disclaimer.
14*b97bf3fdSPer Liden  * Redistributions in binary form must reproduce the above copyright notice,
15*b97bf3fdSPer Liden  * this list of conditions and the following disclaimer in the documentation
16*b97bf3fdSPer Liden  * and/or other materials provided with the distribution.
17*b97bf3fdSPer Liden  * Neither the names of the copyright holders nor the names of its
18*b97bf3fdSPer Liden  * contributors may be used to endorse or promote products derived from this
19*b97bf3fdSPer Liden  * software without specific prior written permission.
20*b97bf3fdSPer Liden  *
21*b97bf3fdSPer Liden  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22*b97bf3fdSPer Liden  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*b97bf3fdSPer Liden  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*b97bf3fdSPer Liden  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25*b97bf3fdSPer Liden  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26*b97bf3fdSPer Liden  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27*b97bf3fdSPer Liden  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*b97bf3fdSPer Liden  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*b97bf3fdSPer Liden  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30*b97bf3fdSPer Liden  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31*b97bf3fdSPer Liden  * POSSIBILITY OF SUCH DAMAGE.
32*b97bf3fdSPer Liden  */
33*b97bf3fdSPer Liden 
34*b97bf3fdSPer Liden #include "core.h"
35*b97bf3fdSPer Liden #include "cluster.h"
36*b97bf3fdSPer Liden #include "dbg.h"
37*b97bf3fdSPer Liden #include "link.h"
38*b97bf3fdSPer Liden #include "msg.h"
39*b97bf3fdSPer Liden #include "name_distr.h"
40*b97bf3fdSPer Liden 
41*b97bf3fdSPer Liden #undef  DBG_OUTPUT
42*b97bf3fdSPer Liden #define DBG_OUTPUT NULL
43*b97bf3fdSPer Liden 
44*b97bf3fdSPer Liden #define ITEM_SIZE sizeof(struct distr_item)
45*b97bf3fdSPer Liden 
46*b97bf3fdSPer Liden /**
47*b97bf3fdSPer Liden  * struct distr_item - publication info distributed to other nodes
48*b97bf3fdSPer Liden  * @type: name sequence type
49*b97bf3fdSPer Liden  * @lower: name sequence lower bound
50*b97bf3fdSPer Liden  * @upper: name sequence upper bound
51*b97bf3fdSPer Liden  * @ref: publishing port reference
52*b97bf3fdSPer Liden  * @key: publication key
53*b97bf3fdSPer Liden  *
54*b97bf3fdSPer Liden  * ===> All fields are stored in network byte order. <===
55*b97bf3fdSPer Liden  *
56*b97bf3fdSPer Liden  * First 3 fields identify (name or) name sequence being published.
57*b97bf3fdSPer Liden  * Reference field uniquely identifies port that published name sequence.
58*b97bf3fdSPer Liden  * Key field uniquely identifies publication, in the event a port has
59*b97bf3fdSPer Liden  * multiple publications of the same name sequence.
60*b97bf3fdSPer Liden  *
61*b97bf3fdSPer Liden  * Note: There is no field that identifies the publishing node because it is
62*b97bf3fdSPer Liden  * the same for all items contained within a publication message.
63*b97bf3fdSPer Liden  */
64*b97bf3fdSPer Liden 
65*b97bf3fdSPer Liden struct distr_item {
66*b97bf3fdSPer Liden 	u32 type;
67*b97bf3fdSPer Liden 	u32 lower;
68*b97bf3fdSPer Liden 	u32 upper;
69*b97bf3fdSPer Liden 	u32 ref;
70*b97bf3fdSPer Liden 	u32 key;
71*b97bf3fdSPer Liden };
72*b97bf3fdSPer Liden 
73*b97bf3fdSPer Liden /**
74*b97bf3fdSPer Liden  * List of externally visible publications by this node --
75*b97bf3fdSPer Liden  * that is, all publications having scope > TIPC_NODE_SCOPE.
76*b97bf3fdSPer Liden  */
77*b97bf3fdSPer Liden 
78*b97bf3fdSPer Liden static LIST_HEAD(publ_root);
79*b97bf3fdSPer Liden static u32 publ_cnt = 0;
80*b97bf3fdSPer Liden 
81*b97bf3fdSPer Liden /**
82*b97bf3fdSPer Liden  * publ_to_item - add publication info to a publication message
83*b97bf3fdSPer Liden  */
84*b97bf3fdSPer Liden 
85*b97bf3fdSPer Liden static void publ_to_item(struct distr_item *i, struct publication *p)
86*b97bf3fdSPer Liden {
87*b97bf3fdSPer Liden 	i->type = htonl(p->type);
88*b97bf3fdSPer Liden 	i->lower = htonl(p->lower);
89*b97bf3fdSPer Liden 	i->upper = htonl(p->upper);
90*b97bf3fdSPer Liden 	i->ref = htonl(p->ref);
91*b97bf3fdSPer Liden 	i->key = htonl(p->key);
92*b97bf3fdSPer Liden 	dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper);
93*b97bf3fdSPer Liden }
94*b97bf3fdSPer Liden 
95*b97bf3fdSPer Liden /**
96*b97bf3fdSPer Liden  * named_prepare_buf - allocate & initialize a publication message
97*b97bf3fdSPer Liden  */
98*b97bf3fdSPer Liden 
99*b97bf3fdSPer Liden static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest)
100*b97bf3fdSPer Liden {
101*b97bf3fdSPer Liden 	struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size);
102*b97bf3fdSPer Liden 	struct tipc_msg *msg;
103*b97bf3fdSPer Liden 
104*b97bf3fdSPer Liden 	if (buf != NULL) {
105*b97bf3fdSPer Liden 		msg = buf_msg(buf);
106*b97bf3fdSPer Liden 		msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK,
107*b97bf3fdSPer Liden 			 LONG_H_SIZE, dest);
108*b97bf3fdSPer Liden 		msg_set_size(msg, LONG_H_SIZE + size);
109*b97bf3fdSPer Liden 	}
110*b97bf3fdSPer Liden 	return buf;
111*b97bf3fdSPer Liden }
112*b97bf3fdSPer Liden 
113*b97bf3fdSPer Liden /**
114*b97bf3fdSPer Liden  * named_publish - tell other nodes about a new publication by this node
115*b97bf3fdSPer Liden  */
116*b97bf3fdSPer Liden 
117*b97bf3fdSPer Liden void named_publish(struct publication *publ)
118*b97bf3fdSPer Liden {
119*b97bf3fdSPer Liden 	struct sk_buff *buf;
120*b97bf3fdSPer Liden 	struct distr_item *item;
121*b97bf3fdSPer Liden 
122*b97bf3fdSPer Liden 	list_add(&publ->local_list, &publ_root);
123*b97bf3fdSPer Liden 	publ_cnt++;
124*b97bf3fdSPer Liden 
125*b97bf3fdSPer Liden 	buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
126*b97bf3fdSPer Liden 	if (!buf) {
127*b97bf3fdSPer Liden 		warn("Memory squeeze; failed to distribute publication\n");
128*b97bf3fdSPer Liden 		return;
129*b97bf3fdSPer Liden 	}
130*b97bf3fdSPer Liden 
131*b97bf3fdSPer Liden 	item = (struct distr_item *)msg_data(buf_msg(buf));
132*b97bf3fdSPer Liden 	publ_to_item(item, publ);
133*b97bf3fdSPer Liden 	dbg("named_withdraw: broadcasting publish msg\n");
134*b97bf3fdSPer Liden 	cluster_broadcast(buf);
135*b97bf3fdSPer Liden }
136*b97bf3fdSPer Liden 
137*b97bf3fdSPer Liden /**
138*b97bf3fdSPer Liden  * named_withdraw - tell other nodes about a withdrawn publication by this node
139*b97bf3fdSPer Liden  */
140*b97bf3fdSPer Liden 
141*b97bf3fdSPer Liden void named_withdraw(struct publication *publ)
142*b97bf3fdSPer Liden {
143*b97bf3fdSPer Liden 	struct sk_buff *buf;
144*b97bf3fdSPer Liden 	struct distr_item *item;
145*b97bf3fdSPer Liden 
146*b97bf3fdSPer Liden 	list_del(&publ->local_list);
147*b97bf3fdSPer Liden 	publ_cnt--;
148*b97bf3fdSPer Liden 
149*b97bf3fdSPer Liden 	buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0);
150*b97bf3fdSPer Liden 	if (!buf) {
151*b97bf3fdSPer Liden 		warn("Memory squeeze; failed to distribute withdrawal\n");
152*b97bf3fdSPer Liden 		return;
153*b97bf3fdSPer Liden 	}
154*b97bf3fdSPer Liden 
155*b97bf3fdSPer Liden 	item = (struct distr_item *)msg_data(buf_msg(buf));
156*b97bf3fdSPer Liden 	publ_to_item(item, publ);
157*b97bf3fdSPer Liden 	dbg("named_withdraw: broadcasting withdraw msg\n");
158*b97bf3fdSPer Liden 	cluster_broadcast(buf);
159*b97bf3fdSPer Liden }
160*b97bf3fdSPer Liden 
161*b97bf3fdSPer Liden /**
162*b97bf3fdSPer Liden  * named_node_up - tell specified node about all publications by this node
163*b97bf3fdSPer Liden  */
164*b97bf3fdSPer Liden 
165*b97bf3fdSPer Liden void named_node_up(unsigned long node)
166*b97bf3fdSPer Liden {
167*b97bf3fdSPer Liden 	struct publication *publ;
168*b97bf3fdSPer Liden 	struct distr_item *item = 0;
169*b97bf3fdSPer Liden 	struct sk_buff *buf = 0;
170*b97bf3fdSPer Liden 	u32 left = 0;
171*b97bf3fdSPer Liden 	u32 rest;
172*b97bf3fdSPer Liden 	u32 max_item_buf;
173*b97bf3fdSPer Liden 
174*b97bf3fdSPer Liden 	assert(in_own_cluster(node));
175*b97bf3fdSPer Liden 	read_lock_bh(&nametbl_lock);
176*b97bf3fdSPer Liden 	max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
177*b97bf3fdSPer Liden 	max_item_buf *= ITEM_SIZE;
178*b97bf3fdSPer Liden 	rest = publ_cnt * ITEM_SIZE;
179*b97bf3fdSPer Liden 
180*b97bf3fdSPer Liden 	list_for_each_entry(publ, &publ_root, local_list) {
181*b97bf3fdSPer Liden 		if (!buf) {
182*b97bf3fdSPer Liden 			left = (rest <= max_item_buf) ? rest : max_item_buf;
183*b97bf3fdSPer Liden 			rest -= left;
184*b97bf3fdSPer Liden 			buf = named_prepare_buf(PUBLICATION, left, node);
185*b97bf3fdSPer Liden 			if (buf == NULL) {
186*b97bf3fdSPer Liden 				warn("Memory Squeeze; could not send publication\n");
187*b97bf3fdSPer Liden 				goto exit;
188*b97bf3fdSPer Liden 			}
189*b97bf3fdSPer Liden 			item = (struct distr_item *)msg_data(buf_msg(buf));
190*b97bf3fdSPer Liden 		}
191*b97bf3fdSPer Liden 		publ_to_item(item, publ);
192*b97bf3fdSPer Liden 		item++;
193*b97bf3fdSPer Liden 		left -= ITEM_SIZE;
194*b97bf3fdSPer Liden 		if (!left) {
195*b97bf3fdSPer Liden 			msg_set_link_selector(buf_msg(buf), node);
196*b97bf3fdSPer Liden 			dbg("named_node_up: sending publish msg to "
197*b97bf3fdSPer Liden 			    "<%u.%u.%u>\n", tipc_zone(node),
198*b97bf3fdSPer Liden 			    tipc_cluster(node), tipc_node(node));
199*b97bf3fdSPer Liden 			link_send(buf, node, node);
200*b97bf3fdSPer Liden 			buf = 0;
201*b97bf3fdSPer Liden 		}
202*b97bf3fdSPer Liden 	}
203*b97bf3fdSPer Liden exit:
204*b97bf3fdSPer Liden 	read_unlock_bh(&nametbl_lock);
205*b97bf3fdSPer Liden }
206*b97bf3fdSPer Liden 
207*b97bf3fdSPer Liden /**
208*b97bf3fdSPer Liden  * node_is_down - remove publication associated with a failed node
209*b97bf3fdSPer Liden  *
210*b97bf3fdSPer Liden  * Invoked for each publication issued by a newly failed node.
211*b97bf3fdSPer Liden  * Removes publication structure from name table & deletes it.
212*b97bf3fdSPer Liden  * In rare cases the link may have come back up again when this
213*b97bf3fdSPer Liden  * function is called, and we have two items representing the same
214*b97bf3fdSPer Liden  * publication. Nudge this item's key to distinguish it from the other.
215*b97bf3fdSPer Liden  * (Note: Publication's node subscription is already unsubscribed.)
216*b97bf3fdSPer Liden  */
217*b97bf3fdSPer Liden 
218*b97bf3fdSPer Liden static void node_is_down(struct publication *publ)
219*b97bf3fdSPer Liden {
220*b97bf3fdSPer Liden 	struct publication *p;
221*b97bf3fdSPer Liden         write_lock_bh(&nametbl_lock);
222*b97bf3fdSPer Liden 	dbg("node_is_down: withdrawing %u, %u, %u\n",
223*b97bf3fdSPer Liden 	    publ->type, publ->lower, publ->upper);
224*b97bf3fdSPer Liden         publ->key += 1222345;
225*b97bf3fdSPer Liden 	p = nametbl_remove_publ(publ->type, publ->lower,
226*b97bf3fdSPer Liden 				publ->node, publ->ref, publ->key);
227*b97bf3fdSPer Liden         assert(p == publ);
228*b97bf3fdSPer Liden 	write_unlock_bh(&nametbl_lock);
229*b97bf3fdSPer Liden 	if (publ)
230*b97bf3fdSPer Liden 		kfree(publ);
231*b97bf3fdSPer Liden }
232*b97bf3fdSPer Liden 
233*b97bf3fdSPer Liden /**
234*b97bf3fdSPer Liden  * named_recv - process name table update message sent by another node
235*b97bf3fdSPer Liden  */
236*b97bf3fdSPer Liden 
237*b97bf3fdSPer Liden void named_recv(struct sk_buff *buf)
238*b97bf3fdSPer Liden {
239*b97bf3fdSPer Liden 	struct publication *publ;
240*b97bf3fdSPer Liden 	struct tipc_msg *msg = buf_msg(buf);
241*b97bf3fdSPer Liden 	struct distr_item *item = (struct distr_item *)msg_data(msg);
242*b97bf3fdSPer Liden 	u32 count = msg_data_sz(msg) / ITEM_SIZE;
243*b97bf3fdSPer Liden 
244*b97bf3fdSPer Liden 	write_lock_bh(&nametbl_lock);
245*b97bf3fdSPer Liden 	while (count--) {
246*b97bf3fdSPer Liden 		if (msg_type(msg) == PUBLICATION) {
247*b97bf3fdSPer Liden 			dbg("named_recv: got publication for %u, %u, %u\n",
248*b97bf3fdSPer Liden 			    ntohl(item->type), ntohl(item->lower),
249*b97bf3fdSPer Liden 			    ntohl(item->upper));
250*b97bf3fdSPer Liden 			publ = nametbl_insert_publ(ntohl(item->type),
251*b97bf3fdSPer Liden 						   ntohl(item->lower),
252*b97bf3fdSPer Liden 						   ntohl(item->upper),
253*b97bf3fdSPer Liden 						   TIPC_CLUSTER_SCOPE,
254*b97bf3fdSPer Liden 						   msg_orignode(msg),
255*b97bf3fdSPer Liden 						   ntohl(item->ref),
256*b97bf3fdSPer Liden 						   ntohl(item->key));
257*b97bf3fdSPer Liden 			if (publ) {
258*b97bf3fdSPer Liden 				nodesub_subscribe(&publ->subscr,
259*b97bf3fdSPer Liden 						  msg_orignode(msg),
260*b97bf3fdSPer Liden 						  publ,
261*b97bf3fdSPer Liden 						  (net_ev_handler)node_is_down);
262*b97bf3fdSPer Liden 			}
263*b97bf3fdSPer Liden 		} else if (msg_type(msg) == WITHDRAWAL) {
264*b97bf3fdSPer Liden 			dbg("named_recv: got withdrawl for %u, %u, %u\n",
265*b97bf3fdSPer Liden 			    ntohl(item->type), ntohl(item->lower),
266*b97bf3fdSPer Liden 			    ntohl(item->upper));
267*b97bf3fdSPer Liden 			publ = nametbl_remove_publ(ntohl(item->type),
268*b97bf3fdSPer Liden 						   ntohl(item->lower),
269*b97bf3fdSPer Liden 						   msg_orignode(msg),
270*b97bf3fdSPer Liden 						   ntohl(item->ref),
271*b97bf3fdSPer Liden 						   ntohl(item->key));
272*b97bf3fdSPer Liden 
273*b97bf3fdSPer Liden 			if (publ) {
274*b97bf3fdSPer Liden 				nodesub_unsubscribe(&publ->subscr);
275*b97bf3fdSPer Liden         			kfree(publ);
276*b97bf3fdSPer Liden 			}
277*b97bf3fdSPer Liden 		} else {
278*b97bf3fdSPer Liden 			warn("named_recv: unknown msg\n");
279*b97bf3fdSPer Liden 		}
280*b97bf3fdSPer Liden 		item++;
281*b97bf3fdSPer Liden 	}
282*b97bf3fdSPer Liden 	write_unlock_bh(&nametbl_lock);
283*b97bf3fdSPer Liden 	buf_discard(buf);
284*b97bf3fdSPer Liden }
285*b97bf3fdSPer Liden 
286*b97bf3fdSPer Liden /**
287*b97bf3fdSPer Liden  * named_reinit - re-initialize local publication list
288*b97bf3fdSPer Liden  *
289*b97bf3fdSPer Liden  * This routine is called whenever TIPC networking is (re)enabled.
290*b97bf3fdSPer Liden  * All existing publications by this node that have "cluster" or "zone" scope
291*b97bf3fdSPer Liden  * are updated to reflect the node's current network address.
292*b97bf3fdSPer Liden  * (If the node's address is unchanged, the update loop terminates immediately.)
293*b97bf3fdSPer Liden  */
294*b97bf3fdSPer Liden 
295*b97bf3fdSPer Liden void named_reinit(void)
296*b97bf3fdSPer Liden {
297*b97bf3fdSPer Liden 	struct publication *publ;
298*b97bf3fdSPer Liden 
299*b97bf3fdSPer Liden 	write_lock_bh(&nametbl_lock);
300*b97bf3fdSPer Liden 	list_for_each_entry(publ, &publ_root, local_list) {
301*b97bf3fdSPer Liden 		if (publ->node == tipc_own_addr)
302*b97bf3fdSPer Liden 			break;
303*b97bf3fdSPer Liden 		publ->node = tipc_own_addr;
304*b97bf3fdSPer Liden 	}
305*b97bf3fdSPer Liden 	write_unlock_bh(&nametbl_lock);
306*b97bf3fdSPer Liden }
307