Skip to content

Commit 4a992bb

Browse files
jk-ozlabsdavem330
authored andcommitted
mctp: Implement message fragmentation & reassembly
This change implements MCTP fragmentation (based on route & device MTU), and corresponding reassembly. The MCTP specification only allows for fragmentation on the originating message endpoint, and reassembly on the destination endpoint - intermediate nodes do not need to reassemble/refragment. Consequently, we only fragment in the local transmit path, and reassemble locally-bound packets. Messages are required to be in-order, so we simply cancel reassembly on out-of-order or missing packets. In the fragmentation path, we just break up the message into MTU-sized fragments; the skb structure is a simple copy for now, which we can later improve with a shared data implementation. For reassembly, we keep track of incoming message fragments using the existing tag infrastructure, allocating a key on the (src,dest,tag) tuple, and reassembles matching fragments into a skb->frag_list. Signed-off-by: Jeremy Kerr <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 833ef3b commit 4a992bb

File tree

3 files changed

+361
-44
lines changed

3 files changed

+361
-44
lines changed

include/net/mctp.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,21 @@ struct mctp_sock {
8484
* updates to either list are performed under the netns_mctp->keys
8585
* lock.
8686
*
87-
* - there is a single destruction path for a mctp_sk_key - through socket
88-
* unhash (see mctp_sk_unhash). This performs the list removal under
89-
* keys_lock.
87+
* - a key may have a sk_buff attached as part of an in-progress message
88+
* reassembly (->reasm_head). The reassembly context is protected by
89+
* reasm_lock, which may be acquired with the keys lock (above) held, if
90+
* necessary. Consequently, keys lock *cannot* be acquired with the
91+
* reasm_lock held.
92+
*
93+
* - there are two destruction paths for a mctp_sk_key:
94+
*
95+
* - through socket unhash (see mctp_sk_unhash). This performs the list
96+
* removal under keys_lock.
97+
*
98+
* - where a key is established to receive a reply message: after receiving
99+
* the (complete) reply, or during reassembly errors. Here, we clean up
100+
* the reassembly context (marking reasm_dead, to prevent another from
101+
* starting), and remove the socket from the netns & socket lists.
90102
*/
91103
struct mctp_sk_key {
92104
mctp_eid_t peer_addr;
@@ -102,6 +114,13 @@ struct mctp_sk_key {
102114
/* per-socket list */
103115
struct hlist_node sklist;
104116

117+
/* incoming fragment reassembly context */
118+
spinlock_t reasm_lock;
119+
struct sk_buff *reasm_head;
120+
struct sk_buff **reasm_tailp;
121+
bool reasm_dead;
122+
u8 last_seq;
123+
105124
struct rcu_head rcu;
106125
};
107126

net/mctp/af_mctp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,14 @@ static void mctp_sk_unhash(struct sock *sk)
263263
hlist_for_each_entry_safe(key, tmp, &msk->keys, sklist) {
264264
hlist_del_rcu(&key->sklist);
265265
hlist_del_rcu(&key->hlist);
266+
267+
spin_lock(&key->reasm_lock);
268+
if (key->reasm_head)
269+
kfree_skb(key->reasm_head);
270+
key->reasm_head = NULL;
271+
key->reasm_dead = true;
272+
spin_unlock(&key->reasm_lock);
273+
266274
kfree_rcu(key, rcu);
267275
}
268276
spin_unlock_irqrestore(&net->mctp.keys_lock, flags);

0 commit comments

Comments
 (0)