net.c 9.7 KB
Newer Older
P
Per Liden 已提交
1 2
/*
 * net/tipc/net.c: TIPC network routing code
3
 *
P
Per Liden 已提交
4
 * Copyright (c) 1995-2006, Ericsson AB
P
Per Liden 已提交
5 6 7 8 9 10
 * Copyright (c) 2005, Wind River Systems
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
P
Per Liden 已提交
11 12 13 14 15 16 17 18 19 20 21 22
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
P
Per Liden 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "core.h"
#include "bearer.h"
#include "net.h"
#include "zone.h"
#include "addr.h"
#include "name_table.h"
#include "name_distr.h"
#include "subscr.h"
#include "link.h"
#include "msg.h"
#include "port.h"
#include "bcast.h"
#include "discover.h"
#include "config.h"

52
/*
P
Per Liden 已提交
53 54
 * The TIPC locking policy is designed to ensure a very fine locking
 * granularity, permitting complete parallel access to individual
55
 * port and node/link instances. The code consists of three major
P
Per Liden 已提交
56 57 58
 * locking domains, each protected with their own disjunct set of locks.
 *
 * 1: The routing hierarchy.
59 60 61 62 63
 *    Comprises the structures 'zone', 'cluster', 'node', 'link'
 *    and 'bearer'. The whole hierarchy is protected by a big
 *    read/write lock, tipc_net_lock, to enssure that nothing is added
 *    or removed while code is accessing any of these structures.
 *    This layer must not be called from the two others while they
P
Per Liden 已提交
64 65
 *    hold any of their own locks.
 *    Neither must it itself do any upcalls to the other two before
66
 *    it has released tipc_net_lock and other protective locks.
P
Per Liden 已提交
67
 *
68
 *   Within the tipc_net_lock domain there are two sub-domains;'node' and
P
Per Liden 已提交
69 70
 *   'bearer', where local write operations are permitted,
 *   provided that those are protected by individual spin_locks
71
 *   per instance. Code holding tipc_net_lock(read) and a node spin_lock
P
Per Liden 已提交
72
 *   is permitted to poke around in both the node itself and its
73 74 75
 *   subordinate links. I.e, it can update link counters and queues,
 *   change link state, send protocol messages, and alter the
 *   "active_links" array in the node; but it can _not_ remove a link
P
Per Liden 已提交
76
 *   or a node from the overall structure.
77 78
 *   Correspondingly, individual bearers may change status within a
 *   tipc_net_lock(read), protected by an individual spin_lock ber bearer
79
 *   instance, but it needs tipc_net_lock(write) to remove/add any bearers.
P
Per Liden 已提交
80
 *
81 82 83 84 85
 *
 *  2: The transport level of the protocol.
 *     This consists of the structures port, (and its user level
 *     representations, such as user_port and tipc_sock), reference and
 *     tipc_user (port.c, reg.c, socket.c).
P
Per Liden 已提交
86 87 88
 *
 *     This layer has four different locks:
 *     - The tipc_port spin_lock. This is protecting each port instance
89 90
 *       from parallel data access and removal. Since we can not place
 *       this lock in the port itself, it has been placed in the
P
Per Liden 已提交
91
 *       corresponding reference table entry, which has the same life
92 93 94
 *       cycle as the module. This entry is difficult to access from
 *       outside the TIPC core, however, so a pointer to the lock has
 *       been added in the port instance, -to be used for unlocking
P
Per Liden 已提交
95
 *       only.
96 97
 *     - A read/write lock to protect the reference table itself (teg.c).
 *       (Nobody is using read-only access to this, so it can just as
P
Per Liden 已提交
98 99
 *       well be changed to a spin_lock)
 *     - A spin lock to protect the registry of kernel/driver users (reg.c)
100
 *     - A global spin_lock (tipc_port_lock), which only task is to ensure
P
Per Liden 已提交
101 102 103 104
 *       consistency where more than one port is involved in an operation,
 *       i.e., whe a port is part of a linked list of ports.
 *       There are two such lists; 'port_list', which is used for management,
 *       and 'wait_list', which is used to queue ports during congestion.
105
 *
P
Per Liden 已提交
106
 *  3: The name table (name_table.c, name_distr.c, subscription.c)
107 108
 *     - There is one big read/write-lock (tipc_nametbl_lock) protecting the
 *       overall name table structure. Nothing must be added/removed to
P
Per Liden 已提交
109 110
 *       this structure without holding write access to it.
 *     - There is one local spin_lock per sub_sequence, which can be seen
111
 *       as a sub-domain to the tipc_nametbl_lock domain. It is used only
P
Per Liden 已提交
112 113
 *       for translation operations, and is needed because a translation
 *       steps the root of the 'publication' linked list between each lookup.
114
 *       This is always used within the scope of a tipc_nametbl_lock(read).
P
Per Liden 已提交
115 116 117
 *     - A local spin_lock protecting the queue of subscriber events.
*/

I
Ingo Molnar 已提交
118
DEFINE_RWLOCK(tipc_net_lock);
119
struct network tipc_net = { NULL };
P
Per Liden 已提交
120

121
struct node *tipc_net_select_remote_node(u32 addr, u32 ref)
P
Per Liden 已提交
122
{
123
	return tipc_zone_select_remote_node(tipc_net.zones[tipc_zone(addr)], addr, ref);
P
Per Liden 已提交
124 125
}

126
u32 tipc_net_select_router(u32 addr, u32 ref)
P
Per Liden 已提交
127
{
128
	return tipc_zone_select_router(tipc_net.zones[tipc_zone(addr)], addr, ref);
P
Per Liden 已提交
129 130
}

A
Adrian Bunk 已提交
131
#if 0
132
u32 tipc_net_next_node(u32 a)
P
Per Liden 已提交
133
{
134 135
	if (tipc_net.zones[tipc_zone(a)])
		return tipc_zone_next_node(a);
P
Per Liden 已提交
136 137
	return 0;
}
A
Adrian Bunk 已提交
138
#endif
P
Per Liden 已提交
139

140
void tipc_net_remove_as_router(u32 router)
P
Per Liden 已提交
141 142 143 144
{
	u32 z_num;

	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
145
		if (!tipc_net.zones[z_num])
P
Per Liden 已提交
146
			continue;
147
		tipc_zone_remove_as_router(tipc_net.zones[z_num], router);
P
Per Liden 已提交
148 149 150
	}
}

151
void tipc_net_send_external_routes(u32 dest)
P
Per Liden 已提交
152 153 154 155
{
	u32 z_num;

	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
156 157
		if (tipc_net.zones[z_num])
			tipc_zone_send_external_routes(tipc_net.zones[z_num], dest);
P
Per Liden 已提交
158 159 160
	}
}

161
static int net_init(void)
P
Per Liden 已提交
162
{
163
	memset(&tipc_net, 0, sizeof(tipc_net));
164
	tipc_net.zones = kcalloc(tipc_max_zones + 1, sizeof(struct _zone *), GFP_ATOMIC);
165
	if (!tipc_net.zones) {
P
Per Liden 已提交
166 167 168 169 170
		return -ENOMEM;
	}
	return TIPC_OK;
}

171
static void net_stop(void)
P
Per Liden 已提交
172 173 174
{
	u32 z_num;

175
	if (!tipc_net.zones)
P
Per Liden 已提交
176 177 178
		return;

	for (z_num = 1; z_num <= tipc_max_zones; z_num++) {
179
		tipc_zone_delete(tipc_net.zones[z_num]);
P
Per Liden 已提交
180
	}
181
	kfree(tipc_net.zones);
182
	tipc_net.zones = NULL;
P
Per Liden 已提交
183 184 185 186 187 188 189 190 191
}

static void net_route_named_msg(struct sk_buff *buf)
{
	struct tipc_msg *msg = buf_msg(buf);
	u32 dnode;
	u32 dport;

	if (!msg_named(msg)) {
192
		msg_dbg(msg, "tipc_net->drop_nam:");
P
Per Liden 已提交
193 194 195 196 197
		buf_discard(buf);
		return;
	}

	dnode = addr_domain(msg_lookup_scope(msg));
198 199
	dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
	dbg("tipc_net->lookup<%u,%u>-><%u,%x>\n",
P
Per Liden 已提交
200 201 202 203
	    msg_nametype(msg), msg_nameinst(msg), dport, dnode);
	if (dport) {
		msg_set_destnode(msg, dnode);
		msg_set_destport(msg, dport);
204
		tipc_net_route_msg(buf);
P
Per Liden 已提交
205 206
		return;
	}
207
	msg_dbg(msg, "tipc_net->rej:NO NAME: ");
P
Per Liden 已提交
208 209 210
	tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
}

211
void tipc_net_route_msg(struct sk_buff *buf)
P
Per Liden 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
{
	struct tipc_msg *msg;
	u32 dnode;

	if (!buf)
		return;
	msg = buf_msg(buf);

	msg_incr_reroute_cnt(msg);
	if (msg_reroute_cnt(msg) > 6) {
		if (msg_errcode(msg)) {
			msg_dbg(msg, "NET>DISC>:");
			buf_discard(buf);
		} else {
			msg_dbg(msg, "NET>REJ>:");
227
			tipc_reject_msg(buf, msg_destport(msg) ?
P
Per Liden 已提交
228 229 230 231 232
					TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME);
		}
		return;
	}

233
	msg_dbg(msg, "tipc_net->rout: ");
P
Per Liden 已提交
234 235 236 237 238

	/* Handle message for this node */
	dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg);
	if (in_scope(dnode, tipc_own_addr)) {
		if (msg_isdata(msg)) {
239
			if (msg_mcast(msg))
240
				tipc_port_recv_mcast(buf, NULL);
P
Per Liden 已提交
241
			else if (msg_destport(msg))
242
				tipc_port_recv_msg(buf);
P
Per Liden 已提交
243 244 245 246 247 248
			else
				net_route_named_msg(buf);
			return;
		}
		switch (msg_user(msg)) {
		case ROUTE_DISTRIBUTOR:
249
			tipc_cltr_recv_routing_table(buf);
P
Per Liden 已提交
250 251
			break;
		case NAME_DISTRIBUTOR:
252
			tipc_named_recv(buf);
P
Per Liden 已提交
253 254
			break;
		case CONN_MANAGER:
255
			tipc_port_recv_proto_msg(buf);
P
Per Liden 已提交
256 257 258 259 260 261 262 263 264 265
			break;
		default:
			msg_dbg(msg,"DROP/NET/<REC<");
			buf_discard(buf);
		}
		return;
	}

	/* Handle message for another node */
	msg_dbg(msg, "NET>SEND>: ");
266
	tipc_link_send(buf, dnode, msg_link_selector(msg));
P
Per Liden 已提交
267 268
}

269
int tipc_net_start(void)
P
Per Liden 已提交
270 271 272 273 274 275 276 277
{
	char addr_string[16];
	int res;

	if (tipc_mode != TIPC_NODE_MODE)
		return -ENOPROTOOPT;

	tipc_mode = TIPC_NET_MODE;
278 279
	tipc_named_reinit();
	tipc_port_reinit();
P
Per Liden 已提交
280

281
	if ((res = tipc_bearer_init()) ||
P
Per Liden 已提交
282
	    (res = net_init()) ||
283 284
	    (res = tipc_cltr_init()) ||
	    (res = tipc_bclink_init())) {
P
Per Liden 已提交
285 286
		return res;
	}
287
	tipc_subscr_stop();
288 289 290
	tipc_cfg_stop();
	tipc_k_signal((Handler)tipc_subscr_start, 0);
	tipc_k_signal((Handler)tipc_cfg_init, 0);
P
Per Liden 已提交
291 292 293 294 295 296
	info("Started in network mode\n");
	info("Own node address %s, network identity %u\n",
	     addr_string_fill(addr_string, tipc_own_addr), tipc_net_id);
	return TIPC_OK;
}

297
void tipc_net_stop(void)
P
Per Liden 已提交
298 299 300
{
	if (tipc_mode != TIPC_NET_MODE)
		return;
301
	write_lock_bh(&tipc_net_lock);
302
	tipc_bearer_stop();
P
Per Liden 已提交
303
	tipc_mode = TIPC_NODE_MODE;
304
	tipc_bclink_stop();
P
Per Liden 已提交
305
	net_stop();
306
	write_unlock_bh(&tipc_net_lock);
P
Per Liden 已提交
307 308 309
	info("Left network mode \n");
}