Merge tag 'fixes-non-critical-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / net / tipc / msg.h
index d5c83d7..9ace47f 100644 (file)
@@ -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:
 
 #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