linux/net/tipc/msg.c
<<
>>
Prefs
   1/*
   2 * net/tipc/msg.c: TIPC message header routines
   3 *
   4 * Copyright (c) 2000-2006, Ericsson AB
   5 * Copyright (c) 2005, Wind River Systems
   6 * All rights reserved.
   7 *
   8 * Redistribution and use in source and binary forms, with or without
   9 * modification, are permitted provided that the following conditions are met:
  10 *
  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.
  19 *
  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
  34 * POSSIBILITY OF SUCH DAMAGE.
  35 */
  36
  37#include "core.h"
  38#include "addr.h"
  39#include "dbg.h"
  40#include "msg.h"
  41#include "bearer.h"
  42
  43u32 tipc_msg_tot_importance(struct tipc_msg *m)
  44{
  45        if (likely(msg_isdata(m))) {
  46                if (likely(msg_orignode(m) == tipc_own_addr))
  47                        return msg_importance(m);
  48                return msg_importance(m) + 4;
  49        }
  50        if ((msg_user(m) == MSG_FRAGMENTER)  &&
  51            (msg_type(m) == FIRST_FRAGMENT))
  52                return msg_importance(msg_get_wrapped(m));
  53        return msg_importance(m);
  54}
  55
  56
  57void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
  58                            u32 hsize, u32 destnode)
  59{
  60        memset(m, 0, hsize);
  61        msg_set_version(m);
  62        msg_set_user(m, user);
  63        msg_set_hdr_sz(m, hsize);
  64        msg_set_size(m, hsize);
  65        msg_set_prevnode(m, tipc_own_addr);
  66        msg_set_type(m, type);
  67        if (!msg_short(m)) {
  68                msg_set_orignode(m, tipc_own_addr);
  69                msg_set_destnode(m, destnode);
  70        }
  71}
  72
  73/**
  74 * tipc_msg_calc_data_size - determine total data size for message
  75 */
  76
  77int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
  78{
  79        int dsz = 0;
  80        int i;
  81
  82        for (i = 0; i < num_sect; i++)
  83                dsz += msg_sect[i].iov_len;
  84        return dsz;
  85}
  86
  87/**
  88 * tipc_msg_build - create message using specified header and data
  89 *
  90 * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
  91 *
  92 * Returns message data size or errno
  93 */
  94
  95int tipc_msg_build(struct tipc_msg *hdr,
  96                            struct iovec const *msg_sect, u32 num_sect,
  97                            int max_size, int usrmem, struct sk_buff** buf)
  98{
  99        int dsz, sz, hsz, pos, res, cnt;
 100
 101        dsz = tipc_msg_calc_data_size(msg_sect, num_sect);
 102        if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
 103                *buf = NULL;
 104                return -EINVAL;
 105        }
 106
 107        pos = hsz = msg_hdr_sz(hdr);
 108        sz = hsz + dsz;
 109        msg_set_size(hdr, sz);
 110        if (unlikely(sz > max_size)) {
 111                *buf = NULL;
 112                return dsz;
 113        }
 114
 115        *buf = buf_acquire(sz);
 116        if (!(*buf))
 117                return -ENOMEM;
 118        skb_copy_to_linear_data(*buf, hdr, hsz);
 119        for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
 120                if (likely(usrmem))
 121                        res = !copy_from_user((*buf)->data + pos,
 122                                              msg_sect[cnt].iov_base,
 123                                              msg_sect[cnt].iov_len);
 124                else
 125                        skb_copy_to_linear_data_offset(*buf, pos,
 126                                                       msg_sect[cnt].iov_base,
 127                                                       msg_sect[cnt].iov_len);
 128                pos += msg_sect[cnt].iov_len;
 129        }
 130        if (likely(res))
 131                return dsz;
 132
 133        buf_discard(*buf);
 134        *buf = NULL;
 135        return -EFAULT;
 136}
 137
 138#ifdef CONFIG_TIPC_DEBUG
 139
 140void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 141{
 142        u32 usr = msg_user(msg);
 143        tipc_printf(buf, str);
 144
 145        switch (usr) {
 146        case MSG_BUNDLER:
 147                tipc_printf(buf, "BNDL::");
 148                tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg));
 149                break;
 150        case BCAST_PROTOCOL:
 151                tipc_printf(buf, "BCASTP::");
 152                break;
 153        case MSG_FRAGMENTER:
 154                tipc_printf(buf, "FRAGM::");
 155                switch (msg_type(msg)) {
 156                case FIRST_FRAGMENT:
 157                        tipc_printf(buf, "FIRST:");
 158                        break;
 159                case FRAGMENT:
 160                        tipc_printf(buf, "BODY:");
 161                        break;
 162                case LAST_FRAGMENT:
 163                        tipc_printf(buf, "LAST:");
 164                        break;
 165                default:
 166                        tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
 167
 168                }
 169                tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
 170                            msg_fragm_no(msg));
 171                break;
 172        case TIPC_LOW_IMPORTANCE:
 173        case TIPC_MEDIUM_IMPORTANCE:
 174        case TIPC_HIGH_IMPORTANCE:
 175        case TIPC_CRITICAL_IMPORTANCE:
 176                tipc_printf(buf, "DAT%u:", msg_user(msg));
 177                if (msg_short(msg)) {
 178                        tipc_printf(buf, "CON:");
 179                        break;
 180                }
 181                switch (msg_type(msg)) {
 182                case TIPC_CONN_MSG:
 183                        tipc_printf(buf, "CON:");
 184                        break;
 185                case TIPC_MCAST_MSG:
 186                        tipc_printf(buf, "MCST:");
 187                        break;
 188                case TIPC_NAMED_MSG:
 189                        tipc_printf(buf, "NAM:");
 190                        break;
 191                case TIPC_DIRECT_MSG:
 192                        tipc_printf(buf, "DIR:");
 193                        break;
 194                default:
 195                        tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg));
 196                }
 197                if (msg_routed(msg) && !msg_non_seq(msg))
 198                        tipc_printf(buf, "ROUT:");
 199                if (msg_reroute_cnt(msg))
 200                        tipc_printf(buf, "REROUTED(%u):",
 201                                    msg_reroute_cnt(msg));
 202                break;
 203        case NAME_DISTRIBUTOR:
 204                tipc_printf(buf, "NMD::");
 205                switch (msg_type(msg)) {
 206                case PUBLICATION:
 207                        tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20);  /* Items */
 208                        break;
 209                case WITHDRAWAL:
 210                        tipc_printf(buf, "WDRW:");
 211                        break;
 212                default:
 213                        tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
 214                }
 215                if (msg_routed(msg))
 216                        tipc_printf(buf, "ROUT:");
 217                if (msg_reroute_cnt(msg))
 218                        tipc_printf(buf, "REROUTED(%u):",
 219                                    msg_reroute_cnt(msg));
 220                break;
 221        case CONN_MANAGER:
 222                tipc_printf(buf, "CONN_MNG:");
 223                switch (msg_type(msg)) {
 224                case CONN_PROBE:
 225                        tipc_printf(buf, "PROBE:");
 226                        break;
 227                case CONN_PROBE_REPLY:
 228                        tipc_printf(buf, "PROBE_REPLY:");
 229                        break;
 230                case CONN_ACK:
 231                        tipc_printf(buf, "CONN_ACK:");
 232                        tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg));
 233                        break;
 234                default:
 235                        tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
 236                }
 237                if (msg_routed(msg))
 238                        tipc_printf(buf, "ROUT:");
 239                if (msg_reroute_cnt(msg))
 240                        tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg));
 241                break;
 242        case LINK_PROTOCOL:
 243                tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg));
 244                switch (msg_type(msg)) {
 245                case STATE_MSG:
 246                        tipc_printf(buf, "STATE:");
 247                        tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :"");
 248                        tipc_printf(buf, "NXS(%u):",msg_next_sent(msg));
 249                        tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg));
 250                        tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg));
 251                        break;
 252                case RESET_MSG:
 253                        tipc_printf(buf, "RESET:");
 254                        if (msg_size(msg) != msg_hdr_sz(msg))
 255                                tipc_printf(buf, "BEAR:%s:",msg_data(msg));
 256                        break;
 257                case ACTIVATE_MSG:
 258                        tipc_printf(buf, "ACTIVATE:");
 259                        break;
 260                default:
 261                        tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
 262                }
 263                tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg));
 264                tipc_printf(buf, "SESS(%u):",msg_session(msg));
 265                break;
 266        case CHANGEOVER_PROTOCOL:
 267                tipc_printf(buf, "TUNL:");
 268                switch (msg_type(msg)) {
 269                case DUPLICATE_MSG:
 270                        tipc_printf(buf, "DUPL:");
 271                        break;
 272                case ORIGINAL_MSG:
 273                        tipc_printf(buf, "ORIG:");
 274                        tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg));
 275                        break;
 276                default:
 277                        tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
 278                }
 279                break;
 280        case ROUTE_DISTRIBUTOR:
 281                tipc_printf(buf, "ROUTING_MNG:");
 282                switch (msg_type(msg)) {
 283                case EXT_ROUTING_TABLE:
 284                        tipc_printf(buf, "EXT_TBL:");
 285                        tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
 286                        break;
 287                case LOCAL_ROUTING_TABLE:
 288                        tipc_printf(buf, "LOCAL_TBL:");
 289                        tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
 290                        break;
 291                case SLAVE_ROUTING_TABLE:
 292                        tipc_printf(buf, "DP_TBL:");
 293                        tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
 294                        break;
 295                case ROUTE_ADDITION:
 296                        tipc_printf(buf, "ADD:");
 297                        tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
 298                        break;
 299                case ROUTE_REMOVAL:
 300                        tipc_printf(buf, "REMOVE:");
 301                        tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
 302                        break;
 303                default:
 304                        tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
 305                }
 306                break;
 307        case LINK_CONFIG:
 308                tipc_printf(buf, "CFG:");
 309                switch (msg_type(msg)) {
 310                case DSC_REQ_MSG:
 311                        tipc_printf(buf, "DSC_REQ:");
 312                        break;
 313                case DSC_RESP_MSG:
 314                        tipc_printf(buf, "DSC_RESP:");
 315                        break;
 316                default:
 317                        tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg));
 318                        break;
 319                }
 320                break;
 321        default:
 322                tipc_printf(buf, "UNKNOWN USER:");
 323        }
 324
 325        switch (usr) {
 326        case CONN_MANAGER:
 327        case TIPC_LOW_IMPORTANCE:
 328        case TIPC_MEDIUM_IMPORTANCE:
 329        case TIPC_HIGH_IMPORTANCE:
 330        case TIPC_CRITICAL_IMPORTANCE:
 331                switch (msg_errcode(msg)) {
 332                case TIPC_OK:
 333                        break;
 334                case TIPC_ERR_NO_NAME:
 335                        tipc_printf(buf, "NO_NAME:");
 336                        break;
 337                case TIPC_ERR_NO_PORT:
 338                        tipc_printf(buf, "NO_PORT:");
 339                        break;
 340                case TIPC_ERR_NO_NODE:
 341                        tipc_printf(buf, "NO_PROC:");
 342                        break;
 343                case TIPC_ERR_OVERLOAD:
 344                        tipc_printf(buf, "OVERLOAD:");
 345                        break;
 346                case TIPC_CONN_SHUTDOWN:
 347                        tipc_printf(buf, "SHUTDOWN:");
 348                        break;
 349                default:
 350                        tipc_printf(buf, "UNKNOWN ERROR(%x):",
 351                                    msg_errcode(msg));
 352                }
 353        default:{}
 354        }
 355
 356        tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg));
 357        tipc_printf(buf, "SZ(%u):", msg_size(msg));
 358        tipc_printf(buf, "SQNO(%u):", msg_seqno(msg));
 359
 360        if (msg_non_seq(msg))
 361                tipc_printf(buf, "NOSEQ:");
 362        else {
 363                tipc_printf(buf, "ACK(%u):", msg_ack(msg));
 364        }
 365        tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg));
 366        tipc_printf(buf, "PRND(%x)", msg_prevnode(msg));
 367
 368        if (msg_isdata(msg)) {
 369                if (msg_named(msg)) {
 370                        tipc_printf(buf, "NTYP(%u):", msg_nametype(msg));
 371                        tipc_printf(buf, "NINST(%u)", msg_nameinst(msg));
 372                }
 373        }
 374
 375        if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) &&
 376            (usr != MSG_BUNDLER)) {
 377                if (!msg_short(msg)) {
 378                        tipc_printf(buf, ":ORIG(%x:%u):",
 379                                    msg_orignode(msg), msg_origport(msg));
 380                        tipc_printf(buf, ":DEST(%x:%u):",
 381                                    msg_destnode(msg), msg_destport(msg));
 382                } else {
 383                        tipc_printf(buf, ":OPRT(%u):", msg_origport(msg));
 384                        tipc_printf(buf, ":DPRT(%u):", msg_destport(msg));
 385                }
 386                if (msg_routed(msg) && !msg_non_seq(msg))
 387                        tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg));
 388        }
 389        if (msg_user(msg) == NAME_DISTRIBUTOR) {
 390                tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg));
 391                tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg));
 392                if (msg_routed(msg)) {
 393                        tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg));
 394                }
 395        }
 396
 397        if (msg_user(msg) ==  LINK_CONFIG) {
 398                u32* raw = (u32*)msg;
 399                struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5];
 400                tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
 401                tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
 402                tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
 403                tipc_media_addr_printf(buf, orig);
 404        }
 405        if (msg_user(msg) == BCAST_PROTOCOL) {
 406                tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
 407                tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg));
 408        }
 409        tipc_printf(buf, "\n");
 410        if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
 411                tipc_msg_dbg(buf, msg_get_wrapped(msg), "      /");
 412        }
 413        if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
 414                tipc_msg_dbg(buf, msg_get_wrapped(msg), "      /");
 415        }
 416}
 417
 418#endif
 419