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