diff options
Diffstat (limited to 'net/tipc/msg.h')
| -rw-r--r-- | net/tipc/msg.h | 143 | 
1 files changed, 127 insertions, 16 deletions
| diff --git a/net/tipc/msg.h b/net/tipc/msg.h index d5c83d7ecb47..9ace47f44a69 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -37,7 +37,7 @@  #ifndef _TIPC_MSG_H  #define _TIPC_MSG_H -#include "bearer.h" +#include <linux/tipc.h>  /*   * Constants and routines used to read and write TIPC payload message headers @@ -45,6 +45,7 @@   * Note: Some items are also used with TIPC internal message headers   */  #define TIPC_VERSION              2 +struct plist;  /*   * Payload message users are defined in TIPC's public API: @@ -77,11 +78,37 @@  #define TIPC_MEDIA_ADDR_OFFSET	5 +/** + * TIPC message buffer code + * + * TIPC message buffer headroom reserves space for the worst-case + * link-level device header (in case the message is sent off-node). + * + * Note: Headroom should be a multiple of 4 to ensure the TIPC header fields + *       are word aligned for quicker access + */ +#define BUF_HEADROOM LL_MAX_HEADER + +struct tipc_skb_cb { +	void *handle; +	struct sk_buff *tail; +	bool deferred; +	bool wakeup_pending; +	bool bundling; +	u16 chain_sz; +	u16 chain_imp; +}; + +#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))  struct tipc_msg {  	__be32 hdr[15];  }; +static inline struct tipc_msg *buf_msg(struct sk_buff *skb) +{ +	return (struct tipc_msg *)skb->data; +}  static inline u32 msg_word(struct tipc_msg *m, u32 pos)  { @@ -721,27 +748,111 @@ static inline u32 msg_tot_origport(struct tipc_msg *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); - +struct sk_buff *tipc_buf_acquire(u32 size); +bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, +		      int err); +void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type, +		   u32 hsize, u32 destnode);  struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz,  				uint data_sz, u32 dnode, u32 onode,  				u32 dport, u32 oport, int errcode); -  int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); -  bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu); +bool tipc_msg_make_bundle(struct sk_buff_head *list, +			  struct sk_buff *skb, u32 mtu, u32 dnode); +bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos); +int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, +		   int offset, int dsz, int mtu, struct sk_buff_head *list); +bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode, +			  int *err); +struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); -bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, -			  u32 mtu, u32 dnode); - -int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, -		   int dsz, int mtu, struct sk_buff_head *list); +/* tipc_skb_peek(): peek and reserve first buffer in list + * @list: list to be peeked in + * Returns pointer to first buffer in list, if any + */ +static inline struct sk_buff *tipc_skb_peek(struct sk_buff_head *list, +					    spinlock_t *lock) +{ +	struct sk_buff *skb; + +	spin_lock_bh(lock); +	skb = skb_peek(list); +	if (skb) +		skb_get(skb); +	spin_unlock_bh(lock); +	return skb; +} + +/* tipc_skb_peek_port(): find a destination port, ignoring all destinations + *                       up to and including 'filter'. + * Note: ignoring previously tried destinations minimizes the risk of + *       contention on the socket lock + * @list: list to be peeked in + * @filter: last destination to be ignored from search + * Returns a destination port number, of applicable. + */ +static inline u32 tipc_skb_peek_port(struct sk_buff_head *list, u32 filter) +{ +	struct sk_buff *skb; +	u32 dport = 0; +	bool ignore = true; + +	spin_lock_bh(&list->lock); +	skb_queue_walk(list, skb) { +		dport = msg_destport(buf_msg(skb)); +		if (!filter || skb_queue_is_last(list, skb)) +			break; +		if (dport == filter) +			ignore = false; +		else if (!ignore) +			break; +	} +	spin_unlock_bh(&list->lock); +	return dport; +} + +/* tipc_skb_dequeue(): unlink first buffer with dest 'dport' from list + * @list: list to be unlinked from + * @dport: selection criteria for buffer to unlink + */ +static inline struct sk_buff *tipc_skb_dequeue(struct sk_buff_head *list, +					       u32 dport) +{ +	struct sk_buff *_skb, *tmp, *skb = NULL; + +	spin_lock_bh(&list->lock); +	skb_queue_walk_safe(list, _skb, tmp) { +		if (msg_destport(buf_msg(_skb)) == dport) { +			__skb_unlink(_skb, list); +			skb = _skb; +			break; +		} +	} +	spin_unlock_bh(&list->lock); +	return skb; +} + +/* tipc_skb_queue_tail(): add buffer to tail of list; + * @list: list to be appended to + * @skb: buffer to append. Always appended + * @dport: the destination port of the buffer + * returns true if dport differs from previous destination + */ +static inline bool tipc_skb_queue_tail(struct sk_buff_head *list, +				       struct sk_buff *skb, u32 dport) +{ +	struct sk_buff *_skb = NULL; +	bool rv = false; -struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list); +	spin_lock_bh(&list->lock); +	_skb = skb_peek_tail(list); +	if (!_skb || (msg_destport(buf_msg(_skb)) != dport) || +	    (skb_queue_len(list) > 32)) +		rv = true; +	__skb_queue_tail(list, skb); +	spin_unlock_bh(&list->lock); +	return rv; +}  #endif |