tipc: Set name lookup scope field properly in all data messages
[deliverable/linux.git] / net / tipc / port.c
CommitLineData
b97bf3fd
PL
1/*
2 * net/tipc/port.c: TIPC port code
c4307285 3 *
05646c91 4 * Copyright (c) 1992-2007, Ericsson AB
23dd4cce 5 * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
b97bf3fd
PL
6 * All rights reserved.
7 *
9ea1fd3c 8 * Redistribution and use in source and binary forms, with or without
b97bf3fd
PL
9 * modification, are permitted provided that the following conditions are met:
10 *
9ea1fd3c
PL
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
b97bf3fd 19 *
9ea1fd3c
PL
20 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
b97bf3fd
PL
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include "core.h"
38#include "config.h"
b97bf3fd 39#include "port.h"
b97bf3fd 40#include "name_table.h"
b97bf3fd
PL
41
42/* Connection management: */
43#define PROBING_INTERVAL 3600000 /* [ms] => 1 h */
44#define CONFIRMED 0
45#define PROBING 1
46
47#define MAX_REJECT_SIZE 1024
48
e3ec9c7d
AS
49static struct sk_buff *msg_queue_head;
50static struct sk_buff *msg_queue_tail;
b97bf3fd 51
34af946a
IM
52DEFINE_SPINLOCK(tipc_port_list_lock);
53static DEFINE_SPINLOCK(queue_lock);
b97bf3fd 54
4323add6 55static LIST_HEAD(ports);
b97bf3fd 56static void port_handle_node_down(unsigned long ref);
23dd4cce
AS
57static struct sk_buff *port_build_self_abort_msg(struct tipc_port *, u32 err);
58static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *, u32 err);
b97bf3fd
PL
59static void port_timeout(unsigned long ref);
60
61
23dd4cce 62static u32 port_peernode(struct tipc_port *p_ptr)
b97bf3fd 63{
23dd4cce 64 return msg_destnode(&p_ptr->phdr);
b97bf3fd
PL
65}
66
23dd4cce 67static u32 port_peerport(struct tipc_port *p_ptr)
b97bf3fd 68{
23dd4cce 69 return msg_destport(&p_ptr->phdr);
b97bf3fd
PL
70}
71
b97bf3fd
PL
72/**
73 * tipc_multicast - send a multicast message to local and remote destinations
74 */
75
38f232ea 76int tipc_multicast(u32 ref, struct tipc_name_seq const *seq,
b97bf3fd
PL
77 u32 num_sect, struct iovec const *msg_sect)
78{
79 struct tipc_msg *hdr;
80 struct sk_buff *buf;
81 struct sk_buff *ibuf = NULL;
82 struct port_list dports = {0, NULL, };
23dd4cce 83 struct tipc_port *oport = tipc_port_deref(ref);
b97bf3fd
PL
84 int ext_targets;
85 int res;
86
87 if (unlikely(!oport))
88 return -EINVAL;
89
90 /* Create multicast message */
91
23dd4cce 92 hdr = &oport->phdr;
b97bf3fd 93 msg_set_type(hdr, TIPC_MCAST_MSG);
53b94364 94 msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE);
b97bf3fd
PL
95 msg_set_nametype(hdr, seq->type);
96 msg_set_namelower(hdr, seq->lower);
97 msg_set_nameupper(hdr, seq->upper);
98 msg_set_hdr_sz(hdr, MCAST_H_SIZE);
c68ca7b7 99 res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
b97bf3fd
PL
100 !oport->user_port, &buf);
101 if (unlikely(!buf))
102 return res;
103
104 /* Figure out where to send multicast message */
105
4323add6
PL
106 ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper,
107 TIPC_NODE_SCOPE, &dports);
c4307285
YH
108
109 /* Send message to destinations (duplicate it only if necessary) */
b97bf3fd
PL
110
111 if (ext_targets) {
112 if (dports.count != 0) {
113 ibuf = skb_copy(buf, GFP_ATOMIC);
114 if (ibuf == NULL) {
4323add6 115 tipc_port_list_free(&dports);
b97bf3fd
PL
116 buf_discard(buf);
117 return -ENOMEM;
118 }
119 }
4323add6 120 res = tipc_bclink_send_msg(buf);
a016892c 121 if ((res < 0) && (dports.count != 0))
b97bf3fd 122 buf_discard(ibuf);
b97bf3fd
PL
123 } else {
124 ibuf = buf;
125 }
126
127 if (res >= 0) {
128 if (ibuf)
4323add6 129 tipc_port_recv_mcast(ibuf, &dports);
b97bf3fd 130 } else {
4323add6 131 tipc_port_list_free(&dports);
b97bf3fd
PL
132 }
133 return res;
134}
135
136/**
4323add6 137 * tipc_port_recv_mcast - deliver multicast message to all destination ports
c4307285 138 *
b97bf3fd
PL
139 * If there is no port list, perform a lookup to create one
140 */
141
4323add6 142void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp)
b97bf3fd 143{
0e65967e 144 struct tipc_msg *msg;
b97bf3fd
PL
145 struct port_list dports = {0, NULL, };
146 struct port_list *item = dp;
147 int cnt = 0;
148
b97bf3fd
PL
149 msg = buf_msg(buf);
150
151 /* Create destination port list, if one wasn't supplied */
152
153 if (dp == NULL) {
4323add6 154 tipc_nametbl_mc_translate(msg_nametype(msg),
b97bf3fd
PL
155 msg_namelower(msg),
156 msg_nameupper(msg),
157 TIPC_CLUSTER_SCOPE,
158 &dports);
159 item = dp = &dports;
160 }
161
162 /* Deliver a copy of message to each destination port */
163
164 if (dp->count != 0) {
165 if (dp->count == 1) {
166 msg_set_destport(msg, dp->ports[0]);
4323add6
PL
167 tipc_port_recv_msg(buf);
168 tipc_port_list_free(dp);
b97bf3fd
PL
169 return;
170 }
171 for (; cnt < dp->count; cnt++) {
172 int index = cnt % PLSIZE;
173 struct sk_buff *b = skb_clone(buf, GFP_ATOMIC);
174
175 if (b == NULL) {
a10bd924 176 warn("Unable to deliver multicast message(s)\n");
b97bf3fd
PL
177 goto exit;
178 }
a016892c 179 if ((index == 0) && (cnt != 0))
b97bf3fd 180 item = item->next;
0e65967e 181 msg_set_destport(buf_msg(b), item->ports[index]);
4323add6 182 tipc_port_recv_msg(b);
b97bf3fd
PL
183 }
184 }
185exit:
186 buf_discard(buf);
4323add6 187 tipc_port_list_free(dp);
b97bf3fd
PL
188}
189
190/**
7ef43eba 191 * tipc_createport_raw - create a generic TIPC port
c4307285 192 *
0ea52241 193 * Returns pointer to (locked) TIPC port, or NULL if unable to create it
b97bf3fd
PL
194 */
195
0ea52241 196struct tipc_port *tipc_createport_raw(void *usr_handle,
b97bf3fd
PL
197 u32 (*dispatcher)(struct tipc_port *, struct sk_buff *),
198 void (*wakeup)(struct tipc_port *),
0ea52241 199 const u32 importance)
b97bf3fd 200{
23dd4cce 201 struct tipc_port *p_ptr;
b97bf3fd
PL
202 struct tipc_msg *msg;
203 u32 ref;
204
0da974f4 205 p_ptr = kzalloc(sizeof(*p_ptr), GFP_ATOMIC);
a10bd924
AS
206 if (!p_ptr) {
207 warn("Port creation failed, no memory\n");
0ea52241 208 return NULL;
b97bf3fd 209 }
23dd4cce 210 ref = tipc_ref_acquire(p_ptr, &p_ptr->lock);
b97bf3fd 211 if (!ref) {
a10bd924 212 warn("Port creation failed, reference table exhausted\n");
b97bf3fd 213 kfree(p_ptr);
0ea52241 214 return NULL;
b97bf3fd
PL
215 }
216
23dd4cce
AS
217 p_ptr->usr_handle = usr_handle;
218 p_ptr->max_pkt = MAX_PKT_DEFAULT;
219 p_ptr->ref = ref;
220 msg = &p_ptr->phdr;
c68ca7b7 221 tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0);
b97bf3fd 222 msg_set_origport(msg, ref);
b97bf3fd
PL
223 INIT_LIST_HEAD(&p_ptr->wait_list);
224 INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
b97bf3fd
PL
225 p_ptr->dispatcher = dispatcher;
226 p_ptr->wakeup = wakeup;
1fc54d8f 227 p_ptr->user_port = NULL;
b97bf3fd 228 k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref);
4323add6 229 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd
PL
230 INIT_LIST_HEAD(&p_ptr->publications);
231 INIT_LIST_HEAD(&p_ptr->port_list);
232 list_add_tail(&p_ptr->port_list, &ports);
4323add6 233 spin_unlock_bh(&tipc_port_list_lock);
23dd4cce 234 return p_ptr;
b97bf3fd
PL
235}
236
237int tipc_deleteport(u32 ref)
238{
23dd4cce 239 struct tipc_port *p_ptr;
1fc54d8f 240 struct sk_buff *buf = NULL;
b97bf3fd 241
1fc54d8f 242 tipc_withdraw(ref, 0, NULL);
4323add6 243 p_ptr = tipc_port_lock(ref);
c4307285 244 if (!p_ptr)
b97bf3fd
PL
245 return -EINVAL;
246
4323add6
PL
247 tipc_ref_discard(ref);
248 tipc_port_unlock(p_ptr);
b97bf3fd
PL
249
250 k_cancel_timer(&p_ptr->timer);
23dd4cce 251 if (p_ptr->connected) {
b97bf3fd 252 buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
4323add6 253 tipc_nodesub_unsubscribe(&p_ptr->subscription);
b97bf3fd 254 }
e83504f7 255 kfree(p_ptr->user_port);
b97bf3fd 256
4323add6 257 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd
PL
258 list_del(&p_ptr->port_list);
259 list_del(&p_ptr->wait_list);
4323add6 260 spin_unlock_bh(&tipc_port_list_lock);
b97bf3fd
PL
261 k_term_timer(&p_ptr->timer);
262 kfree(p_ptr);
4323add6 263 tipc_net_route_msg(buf);
0e35fd5e 264 return 0;
b97bf3fd
PL
265}
266
23dd4cce 267static int port_unreliable(struct tipc_port *p_ptr)
b97bf3fd 268{
23dd4cce 269 return msg_src_droppable(&p_ptr->phdr);
b97bf3fd
PL
270}
271
272int tipc_portunreliable(u32 ref, unsigned int *isunreliable)
273{
23dd4cce 274 struct tipc_port *p_ptr;
c4307285 275
4323add6 276 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
277 if (!p_ptr)
278 return -EINVAL;
279 *isunreliable = port_unreliable(p_ptr);
4cec72c8 280 tipc_port_unlock(p_ptr);
0e35fd5e 281 return 0;
b97bf3fd
PL
282}
283
284int tipc_set_portunreliable(u32 ref, unsigned int isunreliable)
285{
23dd4cce 286 struct tipc_port *p_ptr;
c4307285 287
4323add6 288 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
289 if (!p_ptr)
290 return -EINVAL;
23dd4cce 291 msg_set_src_droppable(&p_ptr->phdr, (isunreliable != 0));
4323add6 292 tipc_port_unlock(p_ptr);
0e35fd5e 293 return 0;
b97bf3fd
PL
294}
295
23dd4cce 296static int port_unreturnable(struct tipc_port *p_ptr)
b97bf3fd 297{
23dd4cce 298 return msg_dest_droppable(&p_ptr->phdr);
b97bf3fd
PL
299}
300
301int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable)
302{
23dd4cce 303 struct tipc_port *p_ptr;
c4307285 304
4323add6 305 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
306 if (!p_ptr)
307 return -EINVAL;
308 *isunrejectable = port_unreturnable(p_ptr);
4cec72c8 309 tipc_port_unlock(p_ptr);
0e35fd5e 310 return 0;
b97bf3fd
PL
311}
312
313int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
314{
23dd4cce 315 struct tipc_port *p_ptr;
c4307285 316
4323add6 317 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
318 if (!p_ptr)
319 return -EINVAL;
23dd4cce 320 msg_set_dest_droppable(&p_ptr->phdr, (isunrejectable != 0));
4323add6 321 tipc_port_unlock(p_ptr);
0e35fd5e 322 return 0;
b97bf3fd
PL
323}
324
c4307285
YH
325/*
326 * port_build_proto_msg(): build a port level protocol
327 * or a connection abortion message. Called with
b97bf3fd
PL
328 * tipc_port lock on.
329 */
330static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
331 u32 origport, u32 orignode,
c4307285 332 u32 usr, u32 type, u32 err,
741de3e9 333 u32 ack)
b97bf3fd
PL
334{
335 struct sk_buff *buf;
336 struct tipc_msg *msg;
c4307285 337
31e3c3f6 338 buf = tipc_buf_acquire(LONG_H_SIZE);
b97bf3fd
PL
339 if (buf) {
340 msg = buf_msg(buf);
c68ca7b7 341 tipc_msg_init(msg, usr, type, LONG_H_SIZE, destnode);
75715217 342 msg_set_errcode(msg, err);
b97bf3fd
PL
343 msg_set_destport(msg, destport);
344 msg_set_origport(msg, origport);
b97bf3fd 345 msg_set_orignode(msg, orignode);
b97bf3fd 346 msg_set_msgcnt(msg, ack);
b97bf3fd
PL
347 }
348 return buf;
349}
350
b97bf3fd
PL
351int tipc_reject_msg(struct sk_buff *buf, u32 err)
352{
353 struct tipc_msg *msg = buf_msg(buf);
354 struct sk_buff *rbuf;
355 struct tipc_msg *rmsg;
356 int hdr_sz;
357 u32 imp = msg_importance(msg);
358 u32 data_sz = msg_data_sz(msg);
359
360 if (data_sz > MAX_REJECT_SIZE)
361 data_sz = MAX_REJECT_SIZE;
362 if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE))
363 imp++;
b97bf3fd
PL
364
365 /* discard rejected message if it shouldn't be returned to sender */
366 if (msg_errcode(msg) || msg_dest_droppable(msg)) {
367 buf_discard(buf);
368 return data_sz;
369 }
370
371 /* construct rejected message */
372 if (msg_mcast(msg))
373 hdr_sz = MCAST_H_SIZE;
374 else
375 hdr_sz = LONG_H_SIZE;
31e3c3f6 376 rbuf = tipc_buf_acquire(data_sz + hdr_sz);
b97bf3fd
PL
377 if (rbuf == NULL) {
378 buf_discard(buf);
379 return data_sz;
380 }
381 rmsg = buf_msg(rbuf);
c68ca7b7 382 tipc_msg_init(rmsg, imp, msg_type(msg), hdr_sz, msg_orignode(msg));
75715217 383 msg_set_errcode(rmsg, err);
b97bf3fd 384 msg_set_destport(rmsg, msg_origport(msg));
b97bf3fd 385 msg_set_origport(rmsg, msg_destport(msg));
99c14593 386 if (msg_short(msg)) {
b97bf3fd 387 msg_set_orignode(rmsg, tipc_own_addr);
99c14593
AS
388 /* leave name type & instance as zeroes */
389 } else {
b97bf3fd 390 msg_set_orignode(rmsg, msg_destnode(msg));
99c14593
AS
391 msg_set_nametype(rmsg, msg_nametype(msg));
392 msg_set_nameinst(rmsg, msg_nameinst(msg));
393 }
c4307285 394 msg_set_size(rmsg, data_sz + hdr_sz);
27d7ff46 395 skb_copy_to_linear_data_offset(rbuf, hdr_sz, msg_data(msg), data_sz);
b97bf3fd
PL
396
397 /* send self-abort message when rejecting on a connected port */
398 if (msg_connected(msg)) {
1fc54d8f 399 struct sk_buff *abuf = NULL;
23dd4cce 400 struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
b97bf3fd
PL
401
402 if (p_ptr) {
23dd4cce 403 if (p_ptr->connected)
b97bf3fd 404 abuf = port_build_self_abort_msg(p_ptr, err);
4323add6 405 tipc_port_unlock(p_ptr);
b97bf3fd 406 }
4323add6 407 tipc_net_route_msg(abuf);
b97bf3fd
PL
408 }
409
410 /* send rejected message */
411 buf_discard(buf);
4323add6 412 tipc_net_route_msg(rbuf);
b97bf3fd
PL
413 return data_sz;
414}
415
23dd4cce 416int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr,
4323add6
PL
417 struct iovec const *msg_sect, u32 num_sect,
418 int err)
b97bf3fd
PL
419{
420 struct sk_buff *buf;
421 int res;
422
c68ca7b7 423 res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
b97bf3fd
PL
424 !p_ptr->user_port, &buf);
425 if (!buf)
426 return res;
427
428 return tipc_reject_msg(buf, err);
429}
430
431static void port_timeout(unsigned long ref)
432{
23dd4cce 433 struct tipc_port *p_ptr = tipc_port_lock(ref);
1fc54d8f 434 struct sk_buff *buf = NULL;
b97bf3fd 435
065fd177
AS
436 if (!p_ptr)
437 return;
438
23dd4cce 439 if (!p_ptr->connected) {
065fd177 440 tipc_port_unlock(p_ptr);
b97bf3fd 441 return;
065fd177 442 }
b97bf3fd
PL
443
444 /* Last probe answered ? */
445 if (p_ptr->probing_state == PROBING) {
446 buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
447 } else {
448 buf = port_build_proto_msg(port_peerport(p_ptr),
449 port_peernode(p_ptr),
23dd4cce 450 p_ptr->ref,
b97bf3fd
PL
451 tipc_own_addr,
452 CONN_MANAGER,
453 CONN_PROBE,
c4307285 454 TIPC_OK,
b97bf3fd 455 0);
b97bf3fd
PL
456 p_ptr->probing_state = PROBING;
457 k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
458 }
4323add6
PL
459 tipc_port_unlock(p_ptr);
460 tipc_net_route_msg(buf);
b97bf3fd
PL
461}
462
463
464static void port_handle_node_down(unsigned long ref)
465{
23dd4cce 466 struct tipc_port *p_ptr = tipc_port_lock(ref);
0e65967e 467 struct sk_buff *buf = NULL;
b97bf3fd
PL
468
469 if (!p_ptr)
470 return;
471 buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE);
4323add6
PL
472 tipc_port_unlock(p_ptr);
473 tipc_net_route_msg(buf);
b97bf3fd
PL
474}
475
476
23dd4cce 477static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err)
b97bf3fd 478{
23dd4cce 479 u32 imp = msg_importance(&p_ptr->phdr);
b97bf3fd 480
23dd4cce 481 if (!p_ptr->connected)
1fc54d8f 482 return NULL;
b97bf3fd
PL
483 if (imp < TIPC_CRITICAL_IMPORTANCE)
484 imp++;
23dd4cce 485 return port_build_proto_msg(p_ptr->ref,
b97bf3fd
PL
486 tipc_own_addr,
487 port_peerport(p_ptr),
488 port_peernode(p_ptr),
489 imp,
490 TIPC_CONN_MSG,
c4307285 491 err,
b97bf3fd
PL
492 0);
493}
494
495
23dd4cce 496static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err)
b97bf3fd 497{
23dd4cce 498 u32 imp = msg_importance(&p_ptr->phdr);
b97bf3fd 499
23dd4cce 500 if (!p_ptr->connected)
1fc54d8f 501 return NULL;
b97bf3fd
PL
502 if (imp < TIPC_CRITICAL_IMPORTANCE)
503 imp++;
504 return port_build_proto_msg(port_peerport(p_ptr),
505 port_peernode(p_ptr),
23dd4cce 506 p_ptr->ref,
b97bf3fd
PL
507 tipc_own_addr,
508 imp,
509 TIPC_CONN_MSG,
c4307285 510 err,
b97bf3fd
PL
511 0);
512}
513
4323add6 514void tipc_port_recv_proto_msg(struct sk_buff *buf)
b97bf3fd
PL
515{
516 struct tipc_msg *msg = buf_msg(buf);
23dd4cce 517 struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
b97bf3fd 518 u32 err = TIPC_OK;
1fc54d8f
SR
519 struct sk_buff *r_buf = NULL;
520 struct sk_buff *abort_buf = NULL;
b97bf3fd 521
b97bf3fd
PL
522 if (!p_ptr) {
523 err = TIPC_ERR_NO_PORT;
23dd4cce 524 } else if (p_ptr->connected) {
96d841b7
AS
525 if ((port_peernode(p_ptr) != msg_orignode(msg)) ||
526 (port_peerport(p_ptr) != msg_origport(msg))) {
b97bf3fd 527 err = TIPC_ERR_NO_PORT;
96d841b7 528 } else if (msg_type(msg) == CONN_ACK) {
c4307285 529 int wakeup = tipc_port_congested(p_ptr) &&
23dd4cce 530 p_ptr->congested &&
b97bf3fd
PL
531 p_ptr->wakeup;
532 p_ptr->acked += msg_msgcnt(msg);
4323add6 533 if (tipc_port_congested(p_ptr))
b97bf3fd 534 goto exit;
23dd4cce 535 p_ptr->congested = 0;
b97bf3fd
PL
536 if (!wakeup)
537 goto exit;
23dd4cce 538 p_ptr->wakeup(p_ptr);
b97bf3fd
PL
539 goto exit;
540 }
23dd4cce 541 } else if (p_ptr->published) {
b97bf3fd
PL
542 err = TIPC_ERR_NO_PORT;
543 }
544 if (err) {
545 r_buf = port_build_proto_msg(msg_origport(msg),
c4307285
YH
546 msg_orignode(msg),
547 msg_destport(msg),
b97bf3fd 548 tipc_own_addr,
06d82c91 549 TIPC_HIGH_IMPORTANCE,
b97bf3fd
PL
550 TIPC_CONN_MSG,
551 err,
b97bf3fd
PL
552 0);
553 goto exit;
554 }
555
556 /* All is fine */
557 if (msg_type(msg) == CONN_PROBE) {
c4307285
YH
558 r_buf = port_build_proto_msg(msg_origport(msg),
559 msg_orignode(msg),
560 msg_destport(msg),
561 tipc_own_addr,
b97bf3fd
PL
562 CONN_MANAGER,
563 CONN_PROBE_REPLY,
564 TIPC_OK,
b97bf3fd
PL
565 0);
566 }
567 p_ptr->probing_state = CONFIRMED;
b97bf3fd
PL
568exit:
569 if (p_ptr)
4323add6
PL
570 tipc_port_unlock(p_ptr);
571 tipc_net_route_msg(r_buf);
572 tipc_net_route_msg(abort_buf);
b97bf3fd
PL
573 buf_discard(buf);
574}
575
23dd4cce 576static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id)
b97bf3fd 577{
c4307285 578 struct publication *publ;
b97bf3fd
PL
579
580 if (full_id)
c4307285 581 tipc_printf(buf, "<%u.%u.%u:%u>:",
b97bf3fd 582 tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
23dd4cce 583 tipc_node(tipc_own_addr), p_ptr->ref);
b97bf3fd 584 else
23dd4cce 585 tipc_printf(buf, "%-10u:", p_ptr->ref);
b97bf3fd 586
23dd4cce 587 if (p_ptr->connected) {
c4307285
YH
588 u32 dport = port_peerport(p_ptr);
589 u32 destnode = port_peernode(p_ptr);
590
591 tipc_printf(buf, " connected to <%u.%u.%u:%u>",
592 tipc_zone(destnode), tipc_cluster(destnode),
593 tipc_node(destnode), dport);
23dd4cce 594 if (p_ptr->conn_type != 0)
c4307285 595 tipc_printf(buf, " via {%u,%u}",
23dd4cce
AS
596 p_ptr->conn_type,
597 p_ptr->conn_instance);
598 } else if (p_ptr->published) {
c4307285
YH
599 tipc_printf(buf, " bound to");
600 list_for_each_entry(publ, &p_ptr->publications, pport_list) {
b97bf3fd
PL
601 if (publ->lower == publ->upper)
602 tipc_printf(buf, " {%u,%u}", publ->type,
603 publ->lower);
604 else
c4307285 605 tipc_printf(buf, " {%u,%u,%u}", publ->type,
b97bf3fd 606 publ->lower, publ->upper);
c4307285
YH
607 }
608 }
609 tipc_printf(buf, "\n");
b97bf3fd
PL
610}
611
612#define MAX_PORT_QUERY 32768
613
4323add6 614struct sk_buff *tipc_port_get_ports(void)
b97bf3fd
PL
615{
616 struct sk_buff *buf;
617 struct tlv_desc *rep_tlv;
618 struct print_buf pb;
23dd4cce 619 struct tipc_port *p_ptr;
b97bf3fd
PL
620 int str_len;
621
4323add6 622 buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY));
b97bf3fd
PL
623 if (!buf)
624 return NULL;
625 rep_tlv = (struct tlv_desc *)buf->data;
626
4323add6
PL
627 tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
628 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd 629 list_for_each_entry(p_ptr, &ports, port_list) {
23dd4cce 630 spin_lock_bh(p_ptr->lock);
b97bf3fd 631 port_print(p_ptr, &pb, 0);
23dd4cce 632 spin_unlock_bh(p_ptr->lock);
b97bf3fd 633 }
4323add6
PL
634 spin_unlock_bh(&tipc_port_list_lock);
635 str_len = tipc_printbuf_validate(&pb);
b97bf3fd
PL
636
637 skb_put(buf, TLV_SPACE(str_len));
638 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
639
640 return buf;
641}
642
4323add6 643void tipc_port_reinit(void)
b97bf3fd 644{
23dd4cce 645 struct tipc_port *p_ptr;
b97bf3fd
PL
646 struct tipc_msg *msg;
647
4323add6 648 spin_lock_bh(&tipc_port_list_lock);
b97bf3fd 649 list_for_each_entry(p_ptr, &ports, port_list) {
23dd4cce 650 msg = &p_ptr->phdr;
b97bf3fd
PL
651 if (msg_orignode(msg) == tipc_own_addr)
652 break;
6d4a6672 653 msg_set_prevnode(msg, tipc_own_addr);
b97bf3fd
PL
654 msg_set_orignode(msg, tipc_own_addr);
655 }
4323add6 656 spin_unlock_bh(&tipc_port_list_lock);
b97bf3fd
PL
657}
658
659
660/*
661 * port_dispatcher_sigh(): Signal handler for messages destinated
662 * to the tipc_port interface.
663 */
664
665static void port_dispatcher_sigh(void *dummy)
666{
667 struct sk_buff *buf;
668
669 spin_lock_bh(&queue_lock);
670 buf = msg_queue_head;
1fc54d8f 671 msg_queue_head = NULL;
b97bf3fd
PL
672 spin_unlock_bh(&queue_lock);
673
674 while (buf) {
23dd4cce 675 struct tipc_port *p_ptr;
b97bf3fd
PL
676 struct user_port *up_ptr;
677 struct tipc_portid orig;
678 struct tipc_name_seq dseq;
679 void *usr_handle;
680 int connected;
681 int published;
9688243b 682 u32 message_type;
b97bf3fd
PL
683
684 struct sk_buff *next = buf->next;
685 struct tipc_msg *msg = buf_msg(buf);
686 u32 dref = msg_destport(msg);
c4307285 687
9688243b
AS
688 message_type = msg_type(msg);
689 if (message_type > TIPC_DIRECT_MSG)
690 goto reject; /* Unsupported message type */
691
4323add6 692 p_ptr = tipc_port_lock(dref);
9688243b
AS
693 if (!p_ptr)
694 goto reject; /* Port deleted while msg in queue */
695
b97bf3fd
PL
696 orig.ref = msg_origport(msg);
697 orig.node = msg_orignode(msg);
698 up_ptr = p_ptr->user_port;
699 usr_handle = up_ptr->usr_handle;
23dd4cce
AS
700 connected = p_ptr->connected;
701 published = p_ptr->published;
b97bf3fd
PL
702
703 if (unlikely(msg_errcode(msg)))
704 goto err;
705
9688243b 706 switch (message_type) {
c4307285 707
b97bf3fd
PL
708 case TIPC_CONN_MSG:{
709 tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
710 u32 peer_port = port_peerport(p_ptr);
711 u32 peer_node = port_peernode(p_ptr);
cb7ce914 712 u32 dsz;
b97bf3fd 713
4cec72c8 714 tipc_port_unlock(p_ptr);
5307e469
AS
715 if (unlikely(!cb))
716 goto reject;
b97bf3fd 717 if (unlikely(!connected)) {
84b07c16 718 if (tipc_connect2port(dref, &orig))
b97bf3fd 719 goto reject;
84b07c16
AS
720 } else if ((msg_origport(msg) != peer_port) ||
721 (msg_orignode(msg) != peer_node))
b97bf3fd 722 goto reject;
cb7ce914
AS
723 dsz = msg_data_sz(msg);
724 if (unlikely(dsz &&
725 (++p_ptr->conn_unacked >=
726 TIPC_FLOW_CONTROL_WIN)))
c4307285 727 tipc_acknowledge(dref,
23dd4cce 728 p_ptr->conn_unacked);
b97bf3fd 729 skb_pull(buf, msg_hdr_sz(msg));
cb7ce914 730 cb(usr_handle, dref, &buf, msg_data(msg), dsz);
b97bf3fd
PL
731 break;
732 }
733 case TIPC_DIRECT_MSG:{
734 tipc_msg_event cb = up_ptr->msg_cb;
735
4cec72c8 736 tipc_port_unlock(p_ptr);
5307e469 737 if (unlikely(!cb || connected))
b97bf3fd
PL
738 goto reject;
739 skb_pull(buf, msg_hdr_sz(msg));
c4307285 740 cb(usr_handle, dref, &buf, msg_data(msg),
b97bf3fd
PL
741 msg_data_sz(msg), msg_importance(msg),
742 &orig);
743 break;
744 }
9688243b 745 case TIPC_MCAST_MSG:
b97bf3fd
PL
746 case TIPC_NAMED_MSG:{
747 tipc_named_msg_event cb = up_ptr->named_msg_cb;
748
4cec72c8 749 tipc_port_unlock(p_ptr);
5307e469 750 if (unlikely(!cb || connected || !published))
b97bf3fd
PL
751 goto reject;
752 dseq.type = msg_nametype(msg);
753 dseq.lower = msg_nameinst(msg);
9688243b
AS
754 dseq.upper = (message_type == TIPC_NAMED_MSG)
755 ? dseq.lower : msg_nameupper(msg);
b97bf3fd 756 skb_pull(buf, msg_hdr_sz(msg));
c4307285 757 cb(usr_handle, dref, &buf, msg_data(msg),
b97bf3fd
PL
758 msg_data_sz(msg), msg_importance(msg),
759 &orig, &dseq);
760 break;
761 }
762 }
763 if (buf)
764 buf_discard(buf);
765 buf = next;
766 continue;
767err:
9688243b 768 switch (message_type) {
c4307285 769
b97bf3fd 770 case TIPC_CONN_MSG:{
c4307285 771 tipc_conn_shutdown_event cb =
b97bf3fd
PL
772 up_ptr->conn_err_cb;
773 u32 peer_port = port_peerport(p_ptr);
774 u32 peer_node = port_peernode(p_ptr);
775
4cec72c8 776 tipc_port_unlock(p_ptr);
5307e469 777 if (!cb || !connected)
b97bf3fd 778 break;
5307e469
AS
779 if ((msg_origport(msg) != peer_port) ||
780 (msg_orignode(msg) != peer_node))
b97bf3fd
PL
781 break;
782 tipc_disconnect(dref);
783 skb_pull(buf, msg_hdr_sz(msg));
784 cb(usr_handle, dref, &buf, msg_data(msg),
785 msg_data_sz(msg), msg_errcode(msg));
786 break;
787 }
788 case TIPC_DIRECT_MSG:{
789 tipc_msg_err_event cb = up_ptr->err_cb;
790
4cec72c8 791 tipc_port_unlock(p_ptr);
5307e469 792 if (!cb || connected)
b97bf3fd
PL
793 break;
794 skb_pull(buf, msg_hdr_sz(msg));
795 cb(usr_handle, dref, &buf, msg_data(msg),
796 msg_data_sz(msg), msg_errcode(msg), &orig);
797 break;
798 }
9688243b 799 case TIPC_MCAST_MSG:
b97bf3fd 800 case TIPC_NAMED_MSG:{
c4307285 801 tipc_named_msg_err_event cb =
b97bf3fd
PL
802 up_ptr->named_err_cb;
803
4cec72c8 804 tipc_port_unlock(p_ptr);
5307e469 805 if (!cb || connected)
b97bf3fd
PL
806 break;
807 dseq.type = msg_nametype(msg);
808 dseq.lower = msg_nameinst(msg);
9688243b
AS
809 dseq.upper = (message_type == TIPC_NAMED_MSG)
810 ? dseq.lower : msg_nameupper(msg);
b97bf3fd 811 skb_pull(buf, msg_hdr_sz(msg));
c4307285 812 cb(usr_handle, dref, &buf, msg_data(msg),
b97bf3fd
PL
813 msg_data_sz(msg), msg_errcode(msg), &dseq);
814 break;
815 }
816 }
817 if (buf)
818 buf_discard(buf);
819 buf = next;
820 continue;
821reject:
822 tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
823 buf = next;
824 }
825}
826
827/*
828 * port_dispatcher(): Dispatcher for messages destinated
829 * to the tipc_port interface. Called with port locked.
830 */
831
832static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf)
833{
834 buf->next = NULL;
835 spin_lock_bh(&queue_lock);
836 if (msg_queue_head) {
837 msg_queue_tail->next = buf;
838 msg_queue_tail = buf;
839 } else {
840 msg_queue_tail = msg_queue_head = buf;
4323add6 841 tipc_k_signal((Handler)port_dispatcher_sigh, 0);
b97bf3fd
PL
842 }
843 spin_unlock_bh(&queue_lock);
0e35fd5e 844 return 0;
b97bf3fd
PL
845}
846
c4307285 847/*
b97bf3fd 848 * Wake up port after congestion: Called with port locked,
c4307285 849 *
b97bf3fd
PL
850 */
851
852static void port_wakeup_sh(unsigned long ref)
853{
23dd4cce 854 struct tipc_port *p_ptr;
b97bf3fd 855 struct user_port *up_ptr;
1fc54d8f
SR
856 tipc_continue_event cb = NULL;
857 void *uh = NULL;
b97bf3fd 858
4323add6 859 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
860 if (p_ptr) {
861 up_ptr = p_ptr->user_port;
862 if (up_ptr) {
863 cb = up_ptr->continue_event_cb;
864 uh = up_ptr->usr_handle;
865 }
4323add6 866 tipc_port_unlock(p_ptr);
b97bf3fd
PL
867 }
868 if (cb)
869 cb(uh, ref);
870}
871
872
873static void port_wakeup(struct tipc_port *p_ptr)
874{
4323add6 875 tipc_k_signal((Handler)port_wakeup_sh, p_ptr->ref);
b97bf3fd
PL
876}
877
878void tipc_acknowledge(u32 ref, u32 ack)
879{
23dd4cce 880 struct tipc_port *p_ptr;
1fc54d8f 881 struct sk_buff *buf = NULL;
b97bf3fd 882
4323add6 883 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
884 if (!p_ptr)
885 return;
23dd4cce
AS
886 if (p_ptr->connected) {
887 p_ptr->conn_unacked -= ack;
b97bf3fd
PL
888 buf = port_build_proto_msg(port_peerport(p_ptr),
889 port_peernode(p_ptr),
890 ref,
891 tipc_own_addr,
892 CONN_MANAGER,
893 CONN_ACK,
c4307285 894 TIPC_OK,
b97bf3fd
PL
895 ack);
896 }
4323add6
PL
897 tipc_port_unlock(p_ptr);
898 tipc_net_route_msg(buf);
b97bf3fd
PL
899}
900
901/*
b0c1e928 902 * tipc_createport(): user level call.
b97bf3fd
PL
903 */
904
b0c1e928 905int tipc_createport(void *usr_handle,
c4307285
YH
906 unsigned int importance,
907 tipc_msg_err_event error_cb,
908 tipc_named_msg_err_event named_error_cb,
909 tipc_conn_shutdown_event conn_error_cb,
910 tipc_msg_event msg_cb,
911 tipc_named_msg_event named_msg_cb,
912 tipc_conn_msg_event conn_msg_cb,
b97bf3fd
PL
913 tipc_continue_event continue_event_cb,/* May be zero */
914 u32 *portref)
915{
916 struct user_port *up_ptr;
23dd4cce 917 struct tipc_port *p_ptr;
b97bf3fd 918
0da974f4 919 up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
a10bd924 920 if (!up_ptr) {
a75bf874 921 warn("Port creation failed, no memory\n");
b97bf3fd
PL
922 return -ENOMEM;
923 }
23dd4cce 924 p_ptr = (struct tipc_port *)tipc_createport_raw(NULL, port_dispatcher,
0ea52241
AS
925 port_wakeup, importance);
926 if (!p_ptr) {
b97bf3fd
PL
927 kfree(up_ptr);
928 return -ENOMEM;
929 }
930
931 p_ptr->user_port = up_ptr;
b97bf3fd 932 up_ptr->usr_handle = usr_handle;
23dd4cce 933 up_ptr->ref = p_ptr->ref;
b97bf3fd
PL
934 up_ptr->err_cb = error_cb;
935 up_ptr->named_err_cb = named_error_cb;
936 up_ptr->conn_err_cb = conn_error_cb;
937 up_ptr->msg_cb = msg_cb;
938 up_ptr->named_msg_cb = named_msg_cb;
939 up_ptr->conn_msg_cb = conn_msg_cb;
940 up_ptr->continue_event_cb = continue_event_cb;
23dd4cce 941 *portref = p_ptr->ref;
4323add6 942 tipc_port_unlock(p_ptr);
0e35fd5e 943 return 0;
b97bf3fd
PL
944}
945
b97bf3fd
PL
946int tipc_portimportance(u32 ref, unsigned int *importance)
947{
23dd4cce 948 struct tipc_port *p_ptr;
c4307285 949
4323add6 950 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
951 if (!p_ptr)
952 return -EINVAL;
23dd4cce 953 *importance = (unsigned int)msg_importance(&p_ptr->phdr);
4cec72c8 954 tipc_port_unlock(p_ptr);
0e35fd5e 955 return 0;
b97bf3fd
PL
956}
957
958int tipc_set_portimportance(u32 ref, unsigned int imp)
959{
23dd4cce 960 struct tipc_port *p_ptr;
b97bf3fd
PL
961
962 if (imp > TIPC_CRITICAL_IMPORTANCE)
963 return -EINVAL;
964
4323add6 965 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
966 if (!p_ptr)
967 return -EINVAL;
23dd4cce 968 msg_set_importance(&p_ptr->phdr, (u32)imp);
4cec72c8 969 tipc_port_unlock(p_ptr);
0e35fd5e 970 return 0;
b97bf3fd
PL
971}
972
973
974int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
975{
23dd4cce 976 struct tipc_port *p_ptr;
b97bf3fd
PL
977 struct publication *publ;
978 u32 key;
979 int res = -EINVAL;
980
4323add6 981 p_ptr = tipc_port_lock(ref);
d55b4c63
AB
982 if (!p_ptr)
983 return -EINVAL;
984
23dd4cce 985 if (p_ptr->connected)
b97bf3fd
PL
986 goto exit;
987 if (seq->lower > seq->upper)
988 goto exit;
989 if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE))
990 goto exit;
991 key = ref + p_ptr->pub_count + 1;
992 if (key == ref) {
993 res = -EADDRINUSE;
994 goto exit;
995 }
4323add6 996 publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
23dd4cce 997 scope, p_ptr->ref, key);
b97bf3fd
PL
998 if (publ) {
999 list_add(&publ->pport_list, &p_ptr->publications);
1000 p_ptr->pub_count++;
23dd4cce 1001 p_ptr->published = 1;
0e35fd5e 1002 res = 0;
b97bf3fd
PL
1003 }
1004exit:
4323add6 1005 tipc_port_unlock(p_ptr);
b97bf3fd
PL
1006 return res;
1007}
1008
1009int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
1010{
23dd4cce 1011 struct tipc_port *p_ptr;
b97bf3fd
PL
1012 struct publication *publ;
1013 struct publication *tpubl;
1014 int res = -EINVAL;
c4307285 1015
4323add6 1016 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
1017 if (!p_ptr)
1018 return -EINVAL;
b97bf3fd 1019 if (!seq) {
c4307285 1020 list_for_each_entry_safe(publ, tpubl,
b97bf3fd 1021 &p_ptr->publications, pport_list) {
c4307285 1022 tipc_nametbl_withdraw(publ->type, publ->lower,
4323add6 1023 publ->ref, publ->key);
b97bf3fd 1024 }
0e35fd5e 1025 res = 0;
b97bf3fd 1026 } else {
c4307285 1027 list_for_each_entry_safe(publ, tpubl,
b97bf3fd
PL
1028 &p_ptr->publications, pport_list) {
1029 if (publ->scope != scope)
1030 continue;
1031 if (publ->type != seq->type)
1032 continue;
1033 if (publ->lower != seq->lower)
1034 continue;
1035 if (publ->upper != seq->upper)
1036 break;
c4307285 1037 tipc_nametbl_withdraw(publ->type, publ->lower,
4323add6 1038 publ->ref, publ->key);
0e35fd5e 1039 res = 0;
b97bf3fd
PL
1040 break;
1041 }
1042 }
1043 if (list_empty(&p_ptr->publications))
23dd4cce 1044 p_ptr->published = 0;
4323add6 1045 tipc_port_unlock(p_ptr);
b97bf3fd
PL
1046 return res;
1047}
1048
1049int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
1050{
23dd4cce 1051 struct tipc_port *p_ptr;
b97bf3fd
PL
1052 struct tipc_msg *msg;
1053 int res = -EINVAL;
1054
4323add6 1055 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
1056 if (!p_ptr)
1057 return -EINVAL;
23dd4cce 1058 if (p_ptr->published || p_ptr->connected)
b97bf3fd
PL
1059 goto exit;
1060 if (!peer->ref)
1061 goto exit;
1062
23dd4cce 1063 msg = &p_ptr->phdr;
b97bf3fd
PL
1064 msg_set_destnode(msg, peer->node);
1065 msg_set_destport(msg, peer->ref);
1066 msg_set_orignode(msg, tipc_own_addr);
23dd4cce 1067 msg_set_origport(msg, p_ptr->ref);
b97bf3fd 1068 msg_set_type(msg, TIPC_CONN_MSG);
53b94364 1069 msg_set_lookup_scope(msg, 0);
08c80e9a 1070 msg_set_hdr_sz(msg, SHORT_H_SIZE);
b97bf3fd
PL
1071
1072 p_ptr->probing_interval = PROBING_INTERVAL;
1073 p_ptr->probing_state = CONFIRMED;
23dd4cce 1074 p_ptr->connected = 1;
b97bf3fd
PL
1075 k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
1076
0e65967e 1077 tipc_nodesub_subscribe(&p_ptr->subscription, peer->node,
880b005f 1078 (void *)(unsigned long)ref,
b97bf3fd 1079 (net_ev_handler)port_handle_node_down);
0e35fd5e 1080 res = 0;
b97bf3fd 1081exit:
4323add6 1082 tipc_port_unlock(p_ptr);
23dd4cce 1083 p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
b97bf3fd
PL
1084 return res;
1085}
1086
0c3141e9
AS
1087/**
1088 * tipc_disconnect_port - disconnect port from peer
1089 *
1090 * Port must be locked.
1091 */
1092
1093int tipc_disconnect_port(struct tipc_port *tp_ptr)
1094{
1095 int res;
1096
1097 if (tp_ptr->connected) {
1098 tp_ptr->connected = 0;
1099 /* let timer expire on it's own to avoid deadlock! */
1100 tipc_nodesub_unsubscribe(
23dd4cce 1101 &((struct tipc_port *)tp_ptr)->subscription);
0e35fd5e 1102 res = 0;
0c3141e9
AS
1103 } else {
1104 res = -ENOTCONN;
1105 }
1106 return res;
1107}
1108
b97bf3fd
PL
1109/*
1110 * tipc_disconnect(): Disconnect port form peer.
1111 * This is a node local operation.
1112 */
1113
1114int tipc_disconnect(u32 ref)
1115{
23dd4cce 1116 struct tipc_port *p_ptr;
0c3141e9 1117 int res;
b97bf3fd 1118
4323add6 1119 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
1120 if (!p_ptr)
1121 return -EINVAL;
0c3141e9 1122 res = tipc_disconnect_port((struct tipc_port *)p_ptr);
4323add6 1123 tipc_port_unlock(p_ptr);
b97bf3fd
PL
1124 return res;
1125}
1126
1127/*
1128 * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect
1129 */
1130int tipc_shutdown(u32 ref)
1131{
23dd4cce 1132 struct tipc_port *p_ptr;
1fc54d8f 1133 struct sk_buff *buf = NULL;
b97bf3fd 1134
4323add6 1135 p_ptr = tipc_port_lock(ref);
b97bf3fd
PL
1136 if (!p_ptr)
1137 return -EINVAL;
1138
23dd4cce
AS
1139 if (p_ptr->connected) {
1140 u32 imp = msg_importance(&p_ptr->phdr);
b97bf3fd
PL
1141 if (imp < TIPC_CRITICAL_IMPORTANCE)
1142 imp++;
1143 buf = port_build_proto_msg(port_peerport(p_ptr),
1144 port_peernode(p_ptr),
1145 ref,
1146 tipc_own_addr,
1147 imp,
1148 TIPC_CONN_MSG,
c4307285 1149 TIPC_CONN_SHUTDOWN,
b97bf3fd
PL
1150 0);
1151 }
4323add6
PL
1152 tipc_port_unlock(p_ptr);
1153 tipc_net_route_msg(buf);
b97bf3fd
PL
1154 return tipc_disconnect(ref);
1155}
1156
b97bf3fd 1157/*
4323add6 1158 * tipc_port_recv_sections(): Concatenate and deliver sectioned
b97bf3fd
PL
1159 * message for this node.
1160 */
1161
23dd4cce 1162static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect,
31e3c3f6 1163 struct iovec const *msg_sect)
b97bf3fd
PL
1164{
1165 struct sk_buff *buf;
1166 int res;
c4307285 1167
23dd4cce 1168 res = tipc_msg_build(&sender->phdr, msg_sect, num_sect,
b97bf3fd
PL
1169 MAX_MSG_SIZE, !sender->user_port, &buf);
1170 if (likely(buf))
4323add6 1171 tipc_port_recv_msg(buf);
b97bf3fd
PL
1172 return res;
1173}
1174
1175/**
1176 * tipc_send - send message sections on connection
1177 */
1178
1179int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
1180{
23dd4cce 1181 struct tipc_port *p_ptr;
b97bf3fd
PL
1182 u32 destnode;
1183 int res;
1184
4323add6 1185 p_ptr = tipc_port_deref(ref);
23dd4cce 1186 if (!p_ptr || !p_ptr->connected)
b97bf3fd
PL
1187 return -EINVAL;
1188
23dd4cce 1189 p_ptr->congested = 1;
4323add6 1190 if (!tipc_port_congested(p_ptr)) {
b97bf3fd
PL
1191 destnode = port_peernode(p_ptr);
1192 if (likely(destnode != tipc_own_addr))
4323add6
PL
1193 res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
1194 destnode);
b97bf3fd 1195 else
4323add6 1196 res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
b97bf3fd
PL
1197
1198 if (likely(res != -ELINKCONG)) {
23dd4cce 1199 p_ptr->congested = 0;
cb7ce914
AS
1200 if (res > 0)
1201 p_ptr->sent++;
b97bf3fd
PL
1202 return res;
1203 }
1204 }
1205 if (port_unreliable(p_ptr)) {
23dd4cce 1206 p_ptr->congested = 0;
b97bf3fd 1207 /* Just calculate msg length and return */
c68ca7b7 1208 return tipc_msg_calc_data_size(msg_sect, num_sect);
b97bf3fd
PL
1209 }
1210 return -ELINKCONG;
1211}
1212
b97bf3fd 1213/**
12bae479 1214 * tipc_send2name - send message sections to port name
b97bf3fd
PL
1215 */
1216
12bae479
AS
1217int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
1218 unsigned int num_sect, struct iovec const *msg_sect)
b97bf3fd 1219{
23dd4cce 1220 struct tipc_port *p_ptr;
b97bf3fd
PL
1221 struct tipc_msg *msg;
1222 u32 destnode = domain;
9ccc2eb4 1223 u32 destport;
b97bf3fd
PL
1224 int res;
1225
4323add6 1226 p_ptr = tipc_port_deref(ref);
23dd4cce 1227 if (!p_ptr || p_ptr->connected)
b97bf3fd
PL
1228 return -EINVAL;
1229
23dd4cce 1230 msg = &p_ptr->phdr;
b97bf3fd 1231 msg_set_type(msg, TIPC_NAMED_MSG);
12bae479
AS
1232 msg_set_orignode(msg, tipc_own_addr);
1233 msg_set_origport(msg, ref);
b97bf3fd
PL
1234 msg_set_hdr_sz(msg, LONG_H_SIZE);
1235 msg_set_nametype(msg, name->type);
1236 msg_set_nameinst(msg, name->instance);
c68ca7b7 1237 msg_set_lookup_scope(msg, tipc_addr_scope(domain));
4323add6 1238 destport = tipc_nametbl_translate(name->type, name->instance, &destnode);
b97bf3fd
PL
1239 msg_set_destnode(msg, destnode);
1240 msg_set_destport(msg, destport);
1241
5d9c54c1 1242 if (likely(destport)) {
b97bf3fd 1243 if (likely(destnode == tipc_own_addr))
cb7ce914
AS
1244 res = tipc_port_recv_sections(p_ptr, num_sect,
1245 msg_sect);
1246 else
1247 res = tipc_link_send_sections_fast(p_ptr, msg_sect,
1248 num_sect, destnode);
1249 if (likely(res != -ELINKCONG)) {
1250 if (res > 0)
1251 p_ptr->sent++;
b97bf3fd 1252 return res;
cb7ce914 1253 }
b97bf3fd
PL
1254 if (port_unreliable(p_ptr)) {
1255 /* Just calculate msg length and return */
c68ca7b7 1256 return tipc_msg_calc_data_size(msg_sect, num_sect);
b97bf3fd
PL
1257 }
1258 return -ELINKCONG;
1259 }
c4307285 1260 return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect,
4323add6 1261 TIPC_ERR_NO_NAME);
b97bf3fd
PL
1262}
1263
1264/**
12bae479 1265 * tipc_send2port - send message sections to port identity
b97bf3fd
PL
1266 */
1267
12bae479
AS
1268int tipc_send2port(u32 ref, struct tipc_portid const *dest,
1269 unsigned int num_sect, struct iovec const *msg_sect)
b97bf3fd 1270{
23dd4cce 1271 struct tipc_port *p_ptr;
b97bf3fd
PL
1272 struct tipc_msg *msg;
1273 int res;
1274
4323add6 1275 p_ptr = tipc_port_deref(ref);
23dd4cce 1276 if (!p_ptr || p_ptr->connected)
b97bf3fd
PL
1277 return -EINVAL;
1278
23dd4cce 1279 msg = &p_ptr->phdr;
b97bf3fd 1280 msg_set_type(msg, TIPC_DIRECT_MSG);
53b94364 1281 msg_set_lookup_scope(msg, 0);
12bae479
AS
1282 msg_set_orignode(msg, tipc_own_addr);
1283 msg_set_origport(msg, ref);
b97bf3fd
PL
1284 msg_set_destnode(msg, dest->node);
1285 msg_set_destport(msg, dest->ref);
1286 msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
cb7ce914 1287
b97bf3fd 1288 if (dest->node == tipc_own_addr)
cb7ce914
AS
1289 res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
1290 else
1291 res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
1292 dest->node);
1293 if (likely(res != -ELINKCONG)) {
1294 if (res > 0)
1295 p_ptr->sent++;
b97bf3fd 1296 return res;
cb7ce914 1297 }
b97bf3fd
PL
1298 if (port_unreliable(p_ptr)) {
1299 /* Just calculate msg length and return */
c68ca7b7 1300 return tipc_msg_calc_data_size(msg_sect, num_sect);
b97bf3fd
PL
1301 }
1302 return -ELINKCONG;
1303}
1304
c4307285 1305/**
12bae479 1306 * tipc_send_buf2port - send message buffer to port identity
b97bf3fd
PL
1307 */
1308
12bae479
AS
1309int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
1310 struct sk_buff *buf, unsigned int dsz)
b97bf3fd 1311{
23dd4cce 1312 struct tipc_port *p_ptr;
b97bf3fd
PL
1313 struct tipc_msg *msg;
1314 int res;
1315
23dd4cce
AS
1316 p_ptr = (struct tipc_port *)tipc_ref_deref(ref);
1317 if (!p_ptr || p_ptr->connected)
b97bf3fd
PL
1318 return -EINVAL;
1319
23dd4cce 1320 msg = &p_ptr->phdr;
b97bf3fd 1321 msg_set_type(msg, TIPC_DIRECT_MSG);
12bae479
AS
1322 msg_set_orignode(msg, tipc_own_addr);
1323 msg_set_origport(msg, ref);
b97bf3fd
PL
1324 msg_set_destnode(msg, dest->node);
1325 msg_set_destport(msg, dest->ref);
1326 msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
b97bf3fd
PL
1327 msg_set_size(msg, DIR_MSG_H_SIZE + dsz);
1328 if (skb_cow(buf, DIR_MSG_H_SIZE))
1329 return -ENOMEM;
1330
1331 skb_push(buf, DIR_MSG_H_SIZE);
27d7ff46 1332 skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE);
cb7ce914 1333
b97bf3fd 1334 if (dest->node == tipc_own_addr)
cb7ce914
AS
1335 res = tipc_port_recv_msg(buf);
1336 else
1337 res = tipc_send_buf_fast(buf, dest->node);
1338 if (likely(res != -ELINKCONG)) {
1339 if (res > 0)
1340 p_ptr->sent++;
b97bf3fd 1341 return res;
cb7ce914 1342 }
b97bf3fd
PL
1343 if (port_unreliable(p_ptr))
1344 return dsz;
1345 return -ELINKCONG;
1346}
1347
This page took 0.724338 seconds and 5 git commands to generate.