tipc: start using the new multicast functions
[cascardo/linux.git] / net / tipc / socket.c
index 8d30995..b28eea5 100644 (file)
@@ -53,6 +53,7 @@ static void tipc_data_ready(struct sock *sk);
 static void tipc_write_space(struct sock *sk);
 static int tipc_release(struct socket *sock);
 static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags);
+static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p);
 
 static const struct proto_ops packet_ops;
 static const struct proto_ops stream_ops;
@@ -534,6 +535,58 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
        return mask;
 }
 
+/**
+ * tipc_sendmcast - send multicast message
+ * @sock: socket structure
+ * @seq: destination address
+ * @iov: message data to send
+ * @dsz: total length of message data
+ * @timeo: timeout to wait for wakeup
+ *
+ * Called from function tipc_sendmsg(), which has done all sanity checks
+ * Returns the number of bytes sent on success, or errno
+ */
+static int tipc_sendmcast(struct  socket *sock, struct tipc_name_seq *seq,
+                         struct iovec *iov, size_t dsz, long timeo)
+{
+       struct sock *sk = sock->sk;
+       struct tipc_msg *mhdr = &tipc_sk(sk)->port.phdr;
+       struct sk_buff *buf;
+       uint mtu;
+       int rc;
+
+       msg_set_type(mhdr, TIPC_MCAST_MSG);
+       msg_set_lookup_scope(mhdr, TIPC_CLUSTER_SCOPE);
+       msg_set_destport(mhdr, 0);
+       msg_set_destnode(mhdr, 0);
+       msg_set_nametype(mhdr, seq->type);
+       msg_set_namelower(mhdr, seq->lower);
+       msg_set_nameupper(mhdr, seq->upper);
+       msg_set_hdr_sz(mhdr, MCAST_H_SIZE);
+
+new_mtu:
+       mtu = tipc_bclink_get_mtu();
+       rc = tipc_msg_build2(mhdr, iov, 0, dsz, mtu, &buf);
+       if (unlikely(rc < 0))
+               return rc;
+
+       do {
+               rc = tipc_bclink_xmit(buf);
+               if (likely(rc >= 0)) {
+                       rc = dsz;
+                       break;
+               }
+               if (rc == -EMSGSIZE)
+                       goto new_mtu;
+               if (rc != -ELINKCONG)
+                       break;
+               rc = tipc_wait_for_sndmsg(sock, &timeo);
+               if (rc)
+                       kfree_skb_list(buf);
+       } while (!rc);
+       return rc;
+}
+
 /* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets
  */
 void tipc_sk_mcast_rcv(struct sk_buff *buf)
@@ -669,43 +722,6 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p)
        return 0;
 }
 
-/**
- * tipc_sendmcast - send multicast message
- * @sock: socket structure
- * @seq: destination address
- * @iov: message data to send
- * @dsz: total length of message data
- * @timeo: timeout to wait for wakeup
- *
- * Called from function tipc_sendmsg(), which has done all sanity checks
- * Returns the number of bytes sent on success, or errno
- */
-static int tipc_sendmcast(struct  socket *sock, struct tipc_name_seq *seq,
-                         struct iovec *iov, size_t dsz, long timeo)
-{
-       struct sock *sk = sock->sk;
-       struct tipc_sock *tsk = tipc_sk(sk);
-       int rc;
-
-       do {
-               if (sock->state != SS_READY) {
-                       rc = -EOPNOTSUPP;
-                       break;
-               }
-               rc = tipc_port_mcast_xmit(&tsk->port, seq, iov, dsz);
-               if (likely(rc >= 0)) {
-                       if (sock->state != SS_READY)
-                               sock->state = SS_CONNECTING;
-                       break;
-               }
-               if (rc != -ELINKCONG)
-                       break;
-               rc = tipc_wait_for_sndmsg(sock, &timeo);
-       } while (!rc);
-
-       return rc;
-}
-
 /**
  * tipc_sendmsg - send message in connectionless manner
  * @iocb: if NULL, indicates that socket lock is already held