static void link_set_supervision_props(struct link *l_ptr, u32 tolerance);
 static int  link_send_sections_long(struct tipc_port *sender,
                                    struct iovec const *msg_sect,
-                                   u32 num_sect, u32 destnode);
+                                   u32 num_sect, unsigned int total_len,
+                                   u32 destnode);
 static void link_check_defragm_bufs(struct link *l_ptr);
 static void link_state_event(struct link *l_ptr, u32 event);
 static void link_reset_statistics(struct link *l_ptr);
 int tipc_link_send_sections_fast(struct tipc_port *sender,
                                 struct iovec const *msg_sect,
                                 const u32 num_sect,
+                                unsigned int total_len,
                                 u32 destaddr)
 {
        struct tipc_msg *hdr = &sender->phdr;
         * (Must not hold any locks while building message.)
         */
 
-       res = tipc_msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
-                       !sender->user_port, &buf);
+       res = tipc_msg_build(hdr, msg_sect, num_sect, total_len,
+                            sender->max_pkt, !sender->user_port, &buf);
 
        read_lock_bh(&tipc_net_lock);
        node = tipc_node_find(destaddr);
                                goto again;
 
                        return link_send_sections_long(sender, msg_sect,
-                                                      num_sect, destaddr);
+                                                      num_sect, total_len,
+                                                      destaddr);
                }
                tipc_node_unlock(node);
        }
                return tipc_reject_msg(buf, TIPC_ERR_NO_NODE);
        if (res >= 0)
                return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
-                                                TIPC_ERR_NO_NODE);
+                                                total_len, TIPC_ERR_NO_NODE);
        return res;
 }
 
 static int link_send_sections_long(struct tipc_port *sender,
                                   struct iovec const *msg_sect,
                                   u32 num_sect,
+                                  unsigned int total_len,
                                   u32 destaddr)
 {
        struct link *l_ptr;
        struct tipc_node *node;
        struct tipc_msg *hdr = &sender->phdr;
-       u32 dsz = msg_data_sz(hdr);
+       u32 dsz = total_len;
        u32 max_pkt, fragm_sz, rest;
        struct tipc_msg fragm_hdr;
        struct sk_buff *buf, *buf_chain, *prev;
                        buf_discard(buf_chain);
                }
                return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect,
-                                                TIPC_ERR_NO_NODE);
+                                                total_len, TIPC_ERR_NO_NODE);
        }
 
        /* Append whole chain to send queue: */
 
 int tipc_link_send_sections_fast(struct tipc_port *sender,
                                 struct iovec const *msg_sect,
                                 const u32 num_sect,
+                                unsigned int total_len,
                                 u32 destnode);
 void tipc_link_recv_bundle(struct sk_buff *buf);
 int  tipc_link_recv_fragment(struct sk_buff **pending,
 
        }
 }
 
-/**
- * tipc_msg_calc_data_size - determine total data size for message
- */
-
-int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
-{
-       int dsz = 0;
-       int i;
-
-       for (i = 0; i < num_sect; i++)
-               dsz += msg_sect[i].iov_len;
-       return dsz;
-}
-
 /**
  * tipc_msg_build - create message using specified header and data
  *
  * Returns message data size or errno
  */
 
-int tipc_msg_build(struct tipc_msg *hdr,
-                           struct iovec const *msg_sect, u32 num_sect,
+int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
+                  u32 num_sect, unsigned int total_len,
                            int max_size, int usrmem, struct sk_buff **buf)
 {
        int dsz, sz, hsz, pos, res, cnt;
 
-       dsz = tipc_msg_calc_data_size(msg_sect, num_sect);
-       if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
-               *buf = NULL;
-               return -EINVAL;
-       }
-
+       dsz = total_len;
        pos = hsz = msg_hdr_sz(hdr);
        sz = hsz + dsz;
        msg_set_size(hdr, sz);
 
 u32 tipc_msg_tot_importance(struct tipc_msg *m);
 void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type,
                            u32 hsize, u32 destnode);
-int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect);
-int tipc_msg_build(struct tipc_msg *hdr,
-                           struct iovec const *msg_sect, u32 num_sect,
+int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
+                  u32 num_sect, unsigned int total_len,
                            int max_size, int usrmem, struct sk_buff **buf);
 
 static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
 
  */
 
 int tipc_multicast(u32 ref, struct tipc_name_seq const *seq,
-                  u32 num_sect, struct iovec const *msg_sect)
+                  u32 num_sect, struct iovec const *msg_sect,
+                  unsigned int total_len)
 {
        struct tipc_msg *hdr;
        struct sk_buff *buf;
        msg_set_namelower(hdr, seq->lower);
        msg_set_nameupper(hdr, seq->upper);
        msg_set_hdr_sz(hdr, MCAST_H_SIZE);
-       res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
+       res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE,
                        !oport->user_port, &buf);
        if (unlikely(!buf))
                return res;
 
 int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr,
                              struct iovec const *msg_sect, u32 num_sect,
-                             int err)
+                             unsigned int total_len, int err)
 {
        struct sk_buff *buf;
        int res;
 
-       res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE,
+       res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE,
                        !p_ptr->user_port, &buf);
        if (!buf)
                return res;
  */
 
 static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect,
-                                  struct iovec const *msg_sect)
+                                  struct iovec const *msg_sect,
+                                  unsigned int total_len)
 {
        struct sk_buff *buf;
        int res;
 
-       res = tipc_msg_build(&sender->phdr, msg_sect, num_sect,
+       res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len,
                        MAX_MSG_SIZE, !sender->user_port, &buf);
        if (likely(buf))
                tipc_port_recv_msg(buf);
  * tipc_send - send message sections on connection
  */
 
-int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
+int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect,
+             unsigned int total_len)
 {
        struct tipc_port *p_ptr;
        u32 destnode;
                destnode = port_peernode(p_ptr);
                if (likely(destnode != tipc_own_addr))
                        res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
-                                                          destnode);
+                                                          total_len, destnode);
                else
-                       res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+                       res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect,
+                                                     total_len);
 
                if (likely(res != -ELINKCONG)) {
                        p_ptr->congested = 0;
        }
        if (port_unreliable(p_ptr)) {
                p_ptr->congested = 0;
-               /* Just calculate msg length and return */
-               return tipc_msg_calc_data_size(msg_sect, num_sect);
+               return total_len;
        }
        return -ELINKCONG;
 }
  */
 
 int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
-          unsigned int num_sect, struct iovec const *msg_sect)
+                  unsigned int num_sect, struct iovec const *msg_sect,
+                  unsigned int total_len)
 {
        struct tipc_port *p_ptr;
        struct tipc_msg *msg;
        if (likely(destport)) {
                if (likely(destnode == tipc_own_addr))
                        res = tipc_port_recv_sections(p_ptr, num_sect,
-                                                     msg_sect);
+                                                     msg_sect, total_len);
                else
                        res = tipc_link_send_sections_fast(p_ptr, msg_sect,
-                                                          num_sect, destnode);
+                                                          num_sect, total_len,
+                                                          destnode);
                if (likely(res != -ELINKCONG)) {
                        if (res > 0)
                                p_ptr->sent++;
                        return res;
                }
                if (port_unreliable(p_ptr)) {
-                       /* Just calculate msg length and return */
-                       return tipc_msg_calc_data_size(msg_sect, num_sect);
+                       return total_len;
                }
                return -ELINKCONG;
        }
        return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect,
-                                        TIPC_ERR_NO_NAME);
+                                        total_len, TIPC_ERR_NO_NAME);
 }
 
 /**
  */
 
 int tipc_send2port(u32 ref, struct tipc_portid const *dest,
-          unsigned int num_sect, struct iovec const *msg_sect)
+                  unsigned int num_sect, struct iovec const *msg_sect,
+                  unsigned int total_len)
 {
        struct tipc_port *p_ptr;
        struct tipc_msg *msg;
        msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
 
        if (dest->node == tipc_own_addr)
-               res =  tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+               res =  tipc_port_recv_sections(p_ptr, num_sect, msg_sect,
+                                              total_len);
        else
                res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
-                                                  dest->node);
+                                                  total_len, dest->node);
        if (likely(res != -ELINKCONG)) {
                if (res > 0)
                        p_ptr->sent++;
                return res;
        }
        if (port_unreliable(p_ptr)) {
-               /* Just calculate msg length and return */
-               return tipc_msg_calc_data_size(msg_sect, num_sect);
+               return total_len;
        }
        return -ELINKCONG;
 }
 
 /*
  * TIPC messaging routines
  */
-int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect);
+int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect,
+             unsigned int total_len);
 
 int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain,
-               unsigned int num_sect, struct iovec const *msg_sect);
+                  unsigned int num_sect, struct iovec const *msg_sect,
+                  unsigned int total_len);
 
 int tipc_send2port(u32 portref, struct tipc_portid const *dest,
-               unsigned int num_sect, struct iovec const *msg_sect);
+                  unsigned int num_sect, struct iovec const *msg_sect,
+                  unsigned int total_len);
 
 int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest,
                struct sk_buff *buf, unsigned int dsz);
 
 int tipc_multicast(u32 portref, struct tipc_name_seq const *seq,
-               unsigned int section_count, struct iovec const *msg);
+                  unsigned int section_count, struct iovec const *msg,
+                  unsigned int total_len);
 
 int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr,
                              struct iovec const *msg_sect, u32 num_sect,
-                             int err);
+                             unsigned int total_len, int err);
 struct sk_buff *tipc_port_get_ports(void);
 void tipc_port_recv_proto_msg(struct sk_buff *buf);
 void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
 
                                             &dest->addr.name.name,
                                             dest->addr.name.domain,
                                             m->msg_iovlen,
-                                            m->msg_iov);
+                                            m->msg_iov,
+                                            total_len);
                } else if (dest->addrtype == TIPC_ADDR_ID) {
                        res = tipc_send2port(tport->ref,
                                             &dest->addr.id,
                                             m->msg_iovlen,
-                                            m->msg_iov);
+                                            m->msg_iov,
+                                            total_len);
                } else if (dest->addrtype == TIPC_ADDR_MCAST) {
                        if (needs_conn) {
                                res = -EOPNOTSUPP;
                        res = tipc_multicast(tport->ref,
                                             &dest->addr.nameseq,
                                             m->msg_iovlen,
-                                            m->msg_iov);
+                                            m->msg_iov,
+                                            total_len);
                }
                if (likely(res != -ELINKCONG)) {
                        if (needs_conn && (res >= 0))
                        break;
                }
 
-               res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov);
+               res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov,
+                               total_len);
                if (likely(res != -ELINKCONG))
                        break;
                if (m->msg_flags & MSG_DONTWAIT) {
                                bytes_to_send = curr_left;
                        my_iov.iov_base = curr_start;
                        my_iov.iov_len = bytes_to_send;
-                       res = send_packet(NULL, sock, &my_msg, 0);
+                       res = send_packet(NULL, sock, &my_msg, bytes_to_send);
                        if (res < 0) {
                                if (bytes_sent)
                                        res = bytes_sent;
 
        sub->evt.found_upper = htohl(found_upper, sub->swap);
        sub->evt.port.ref = htohl(port_ref, sub->swap);
        sub->evt.port.node = htohl(node, sub->swap);
-       tipc_send(sub->server_ref, 1, &msg_sect);
+       tipc_send(sub->server_ref, 1, &msg_sect, msg_sect.iov_len);
 }
 
 /**
 
        /* Send an ACK- to complete connection handshaking */
 
-       tipc_send(server_port_ref, 0, NULL);
+       tipc_send(server_port_ref, 0, NULL, 0);
 
        /* Handle optional subscription request */