Skip to content

Commit

Permalink
Merge branch 'tipc-next'
Browse files Browse the repository at this point in the history
Jon Maloy says:

====================
tipc: new unicast transmission code

As a step towards making the data transmission code more maintainable
and performant, we introduce a number of new functions, both for
building, sending and rejecting messages. The new functions will
eventually be used for alla data transmission, user data unicast,
service internal messaging, and multicast/broadcast.

We start with this series, where we introduce the functions, and
let user data unicast and the internal connection protocol use them.
The remaining users will come in a later series.

There are only minor changes to data structures, and no protocol
changes, so the older functions can still be used in parallel for
some time. Until the old functions are removed, we use temporary
names for the new functions, such as tipc_build_msg2, tipc_link_xmit2.

It should be noted that the first two commits are unrelated to the
rest of the series.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 27, 2014
2 parents f5b2650 + 6012052 commit 0ff9275
Show file tree
Hide file tree
Showing 13 changed files with 827 additions and 888 deletions.
417 changes: 158 additions & 259 deletions net/tipc/link.c

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions net/tipc/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,10 @@ void tipc_link_reset_all(struct tipc_node *node);
void tipc_link_reset(struct tipc_link *l_ptr);
void tipc_link_reset_list(unsigned int bearer_id);
int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector);
int tipc_link_xmit2(struct sk_buff *buf, u32 dest, u32 selector);
void tipc_link_names_xmit(struct list_head *message_list, u32 dest);
int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf);
int __tipc_link_xmit2(struct tipc_link *link, struct sk_buff *buf);
int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
u32 tipc_link_get_max_pkt(u32 dest, u32 selector);
int tipc_link_iovec_xmit_fast(struct tipc_port *sender,
Expand Down
282 changes: 271 additions & 11 deletions net/tipc/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,16 @@

#include "core.h"
#include "msg.h"
#include "addr.h"
#include "name_table.h"

u32 tipc_msg_tot_importance(struct tipc_msg *m)
#define MAX_FORWARD_SIZE 1024

static unsigned int align(unsigned int i)
{
if (likely(msg_isdata(m))) {
if (likely(msg_orignode(m) == tipc_own_addr))
return msg_importance(m);
return msg_importance(m) + 4;
}
if ((msg_user(m) == MSG_FRAGMENTER) &&
(msg_type(m) == FIRST_FRAGMENT))
return msg_importance(msg_get_wrapped(m));
return msg_importance(m);
return (i + 3) & ~3u;
}


void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
u32 destnode)
{
Expand Down Expand Up @@ -152,3 +147,268 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
kfree_skb(*buf);
return 0;
}


/**
* tipc_msg_build2 - create buffer chain containing specified header and data
* @mhdr: Message header, to be prepended to data
* @iov: User data
* @offset: Posision in iov to start copying from
* @dsz: Total length of user data
* @pktmax: Max packet size that can be used
* @chain: Buffer or chain of buffers to be returned to caller
* Returns message data size or errno: -ENOMEM, -EFAULT
*/
int tipc_msg_build2(struct tipc_msg *mhdr, struct iovec const *iov,
int offset, int dsz, int pktmax , struct sk_buff **chain)
{
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 *buf, *prev;
char *pktpos;
int rc;

msg_set_size(mhdr, msz);

/* No fragmentation needed? */
if (likely(msz <= pktmax)) {
buf = tipc_buf_acquire(msz);
*chain = buf;
if (unlikely(!buf))
return -ENOMEM;
skb_copy_to_linear_data(buf, mhdr, mhsz);
pktpos = buf->data + mhsz;
if (!dsz || !memcpy_fromiovecend(pktpos, 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 */
*chain = buf = tipc_buf_acquire(pktmax);
if (!buf)
return -ENOMEM;
pktpos = buf->data;
skb_copy_to_linear_data(buf, &pkthdr, INT_H_SIZE);
pktpos += INT_H_SIZE;
pktrem -= INT_H_SIZE;
skb_copy_to_linear_data_offset(buf, INT_H_SIZE, mhdr, mhsz);
pktpos += mhsz;
pktrem -= mhsz;

do {
if (drem < pktrem)
pktrem = drem;

if (memcpy_fromiovecend(pktpos, 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;
prev = buf;
buf = tipc_buf_acquire(pktsz);
if (!buf) {
rc = -ENOMEM;
goto error;
}
prev->next = buf;
msg_set_type(&pkthdr, FRAGMENT);
msg_set_size(&pkthdr, pktsz);
msg_set_fragm_no(&pkthdr, ++pktno);
skb_copy_to_linear_data(buf, &pkthdr, INT_H_SIZE);
pktpos = buf->data + INT_H_SIZE;
pktrem = pktsz - INT_H_SIZE;

} while (1);

msg_set_type(buf_msg(buf), LAST_FRAGMENT);
return dsz;
error:
kfree_skb_list(*chain);
*chain = NULL;
return rc;
}

/**
* tipc_msg_bundle(): Append contents of a buffer to tail of an existing one
* @bbuf: the existing buffer ("bundle")
* @buf: buffer to be appended
* @mtu: max allowable size for the bundle buffer
* Consumes buffer if successful
* Returns true if bundling could be performed, otherwise false
*/
bool tipc_msg_bundle(struct sk_buff *bbuf, struct sk_buff *buf, u32 mtu)
{
struct tipc_msg *bmsg = buf_msg(bbuf);
struct tipc_msg *msg = buf_msg(buf);
unsigned int bsz = msg_size(bmsg);
unsigned int msz = msg_size(msg);
u32 start = align(bsz);
u32 max = mtu - INT_H_SIZE;
u32 pad = start - bsz;

if (likely(msg_user(msg) == MSG_FRAGMENTER))
return false;
if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL))
return false;
if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
return false;
if (likely(msg_user(bmsg) != MSG_BUNDLER))
return false;
if (likely(msg_type(bmsg) != BUNDLE_OPEN))
return false;
if (unlikely(skb_tailroom(bbuf) < (pad + msz)))
return false;
if (unlikely(max < (start + msz)))
return false;

skb_put(bbuf, pad + msz);
skb_copy_to_linear_data_offset(bbuf, start, buf->data, msz);
msg_set_size(bmsg, start + msz);
msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1);
bbuf->next = buf->next;
kfree_skb(buf);
return true;
}

/**
* tipc_msg_make_bundle(): Create bundle buf and append message to its tail
* @buf: buffer to be appended and replaced
* @mtu: max allowable size for the bundle buffer, inclusive header
* @dnode: destination node for message. (Not always present in header)
* Replaces buffer if successful
* Returns true if sucess, otherwise false
*/
bool tipc_msg_make_bundle(struct sk_buff **buf, u32 mtu, u32 dnode)
{
struct sk_buff *bbuf;
struct tipc_msg *bmsg;
struct tipc_msg *msg = buf_msg(*buf);
u32 msz = msg_size(msg);
u32 max = mtu - INT_H_SIZE;

if (msg_user(msg) == MSG_FRAGMENTER)
return false;
if (msg_user(msg) == CHANGEOVER_PROTOCOL)
return false;
if (msg_user(msg) == BCAST_PROTOCOL)
return false;
if (msz > (max / 2))
return false;

bbuf = tipc_buf_acquire(max);
if (!bbuf)
return false;

skb_trim(bbuf, INT_H_SIZE);
bmsg = buf_msg(bbuf);
tipc_msg_init(bmsg, MSG_BUNDLER, BUNDLE_OPEN, INT_H_SIZE, dnode);
msg_set_seqno(bmsg, msg_seqno(msg));
msg_set_ack(bmsg, msg_ack(msg));
msg_set_bcast_ack(bmsg, msg_bcast_ack(msg));
bbuf->next = (*buf)->next;
tipc_msg_bundle(bbuf, *buf, mtu);
*buf = bbuf;
return true;
}

/**
* tipc_msg_reverse(): swap source and destination addresses and add error code
* @buf: buffer containing message to be reversed
* @dnode: return value: node where to send message after reversal
* @err: error code to be set in message
* Consumes buffer if failure
* Returns true if success, otherwise false
*/
bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err)
{
struct tipc_msg *msg = buf_msg(buf);
uint imp = msg_importance(msg);
struct tipc_msg ohdr;
uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE);

if (skb_linearize(buf))
goto exit;
if (msg_dest_droppable(msg))
goto exit;
if (msg_errcode(msg))
goto exit;

memcpy(&ohdr, msg, msg_hdr_sz(msg));
imp = min_t(uint, imp + 1, TIPC_CRITICAL_IMPORTANCE);
if (msg_isdata(msg))
msg_set_importance(msg, imp);
msg_set_errcode(msg, err);
msg_set_origport(msg, msg_destport(&ohdr));
msg_set_destport(msg, msg_origport(&ohdr));
msg_set_prevnode(msg, tipc_own_addr);
if (!msg_short(msg)) {
msg_set_orignode(msg, msg_destnode(&ohdr));
msg_set_destnode(msg, msg_orignode(&ohdr));
}
msg_set_size(msg, msg_hdr_sz(msg) + rdsz);
skb_trim(buf, msg_size(msg));
skb_orphan(buf);
*dnode = msg_orignode(&ohdr);
return true;
exit:
kfree_skb(buf);
return false;
}

/**
* tipc_msg_eval: determine fate of message that found no destination
* @buf: the buffer containing the message.
* @dnode: return value: next-hop node, if message to be forwarded
* @err: error code to use, if message to be rejected
*
* Does not consume buffer
* Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error
* code if message to be rejected
*/
int tipc_msg_eval(struct sk_buff *buf, u32 *dnode)
{
struct tipc_msg *msg = buf_msg(buf);
u32 dport;

if (msg_type(msg) != TIPC_NAMED_MSG)
return -TIPC_ERR_NO_PORT;
if (skb_linearize(buf))
return -TIPC_ERR_NO_NAME;
if (msg_data_sz(msg) > MAX_FORWARD_SIZE)
return -TIPC_ERR_NO_NAME;
if (msg_reroute_cnt(msg) > 0)
return -TIPC_ERR_NO_NAME;

*dnode = addr_domain(msg_lookup_scope(msg));
dport = tipc_nametbl_translate(msg_nametype(msg),
msg_nameinst(msg),
dnode);
if (!dport)
return -TIPC_ERR_NO_NAME;
msg_incr_reroute_cnt(msg);
msg_set_destnode(msg, *dnode);
msg_set_destport(msg, dport);
return TIPC_OK;
}
32 changes: 31 additions & 1 deletion net/tipc/msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,11 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
#define FRAGMENT 1
#define LAST_FRAGMENT 2

/* Bundling protocol message types
*/
#define BUNDLE_OPEN 0
#define BUNDLE_CLOSED 1

/*
* Link management protocol message types
*/
Expand Down Expand Up @@ -706,12 +711,37 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
msg_set_bits(m, 9, 0, 0xffff, n);
}

u32 tipc_msg_tot_importance(struct tipc_msg *m);
static inline u32 tipc_msg_tot_importance(struct tipc_msg *m)
{
if ((msg_user(m) == MSG_FRAGMENTER) && (msg_type(m) == FIRST_FRAGMENT))
return msg_importance(msg_get_wrapped(m));
return msg_importance(m);
}

static inline u32 msg_tot_origport(struct tipc_msg *m)
{
if ((msg_user(m) == MSG_FRAGMENTER) && (msg_type(m) == FIRST_FRAGMENT))
return msg_origport(msg_get_wrapped(m));
return msg_origport(m);
}

bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err);

int tipc_msg_eval(struct sk_buff *buf, u32 *dnode);

void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
u32 destnode);

int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
unsigned int len, int max_size, struct sk_buff **buf);

int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf);

bool tipc_msg_bundle(struct sk_buff *bbuf, struct sk_buff *buf, u32 mtu);

bool tipc_msg_make_bundle(struct sk_buff **buf, u32 mtu, u32 dnode);

int tipc_msg_build2(struct tipc_msg *mhdr, struct iovec const *iov,
int offset, int dsz, int mtu , struct sk_buff **chain);

#endif
Loading

0 comments on commit 0ff9275

Please sign in to comment.