void tipc_cltr_send_local_routes(struct cluster *c_ptr, u32 dest) { struct sk_buff *buf; struct tipc_msg *msg; u32 highest = c_ptr->highest_node; u32 n_num; int send = 0; assert(is_slave(dest)); assert(in_own_cluster(c_ptr->addr)); buf = tipc_cltr_prepare_routing_msg(highest, c_ptr->addr); if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, c_ptr->addr); msg_set_type(msg, LOCAL_ROUTING_TABLE); for (n_num = 1; n_num <= highest; n_num++) { if (c_ptr->nodes[n_num] && tipc_node_has_active_links(c_ptr->nodes[n_num])) { send = 1; msg_set_dataoctet(msg, n_num); } } if (send) tipc_link_send(buf, dest, dest); else buf_discard(buf); } else { warn("Memory squeeze: broadcast of local route failed\n"); } }
void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, u32 destnode) { memset(m, 0, hsize); msg_set_version(m); msg_set_user(m, user); msg_set_hdr_sz(m, hsize); msg_set_size(m, hsize); msg_set_prevnode(m, tipc_own_addr); msg_set_type(m, type); msg_set_orignode(m, tipc_own_addr); msg_set_destnode(m, destnode); }
void tipc_cltr_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lower, u32 upper) { struct sk_buff *buf = tipc_cltr_prepare_routing_msg(0, c_ptr->addr); struct tipc_msg *msg; if (buf) { msg = buf_msg(buf); msg_set_remote_node(msg, dest); msg_set_type(msg, ROUTE_REMOVAL); tipc_cltr_multicast(c_ptr, buf, lower, upper); } else { warn("Memory squeeze: broadcast of lost route failed\n"); } }
/** * tipc_msg_build - create buffer chain containing specified header and data * @mhdr: Message header, to be prepended to data * @m: User message * @offset: Posision in iov to start copying from * @dsz: Total length of user data * @pktmax: Max packet size that can be used * @list: Buffer or chain of buffers to be returned to caller * * Returns message data size or errno: -ENOMEM, -EFAULT */ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, int dsz, int pktmax, struct sk_buff_head *list) { int mhsz = msg_hdr_sz(mhdr); int msz = mhsz + dsz; int pktno = 1; int pktsz; int pktrem = pktmax; int drem = dsz; struct tipc_msg pkthdr; struct sk_buff *skb; char *pktpos; int rc; msg_set_size(mhdr, msz); /* No fragmentation needed? */ if (likely(msz <= pktmax)) { skb = tipc_buf_acquire(msz); if (unlikely(!skb)) return -ENOMEM; __skb_queue_tail(list, skb); skb_copy_to_linear_data(skb, mhdr, mhsz); pktpos = skb->data + mhsz; if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, dsz)) return dsz; rc = -EFAULT; goto error; } /* Prepare reusable fragment header */ tipc_msg_init(&pkthdr, MSG_FRAGMENTER, FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(mhdr)); msg_set_size(&pkthdr, pktmax); msg_set_fragm_no(&pkthdr, pktno); /* Prepare first fragment */ skb = tipc_buf_acquire(pktmax); if (!skb) return -ENOMEM; __skb_queue_tail(list, skb); pktpos = skb->data; skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE); pktpos += INT_H_SIZE; pktrem -= INT_H_SIZE; skb_copy_to_linear_data_offset(skb, INT_H_SIZE, mhdr, mhsz); pktpos += mhsz; pktrem -= mhsz; do { if (drem < pktrem) pktrem = drem; if (memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, pktrem)) { rc = -EFAULT; goto error; } drem -= pktrem; offset += pktrem; if (!drem) break; /* Prepare new fragment: */ if (drem < (pktmax - INT_H_SIZE)) pktsz = drem + INT_H_SIZE; else pktsz = pktmax; skb = tipc_buf_acquire(pktsz); if (!skb) { rc = -ENOMEM; goto error; } __skb_queue_tail(list, skb); msg_set_type(&pkthdr, FRAGMENT); msg_set_size(&pkthdr, pktsz); msg_set_fragm_no(&pkthdr, ++pktno); skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE); pktpos = skb->data + INT_H_SIZE; pktrem = pktsz - INT_H_SIZE; } while (1); msg_set_type(buf_msg(skb), LAST_FRAGMENT); return dsz; error: __skb_queue_purge(list); __skb_queue_head_init(list); return rc; }