Commit 13228238 authored by Xin Long's avatar Xin Long Committed by David S. Miller

sctp: add support for the process of unordered idata

Unordered idata process is more complicated than unordered data:

 - It has to add mid into sctp_stream_out to save the next mid value,
   which is separated from ordered idata's.

 - To support pd for unordered idata, another mid and pd_mode need to
   be added to save the message id and pd state in sctp_stream_in.

 - To make  unordered idata reasm easier, it adds a new event queue
   to save frags for idata.

The patch mostly adds the samilar reasm functions for unordered idata
as ordered idata's, and also adjusts some other codes on assign_mid,
abort_pd and ulpevent_data for idata.
Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Acked-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 65f5e357
...@@ -413,6 +413,14 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new); ...@@ -413,6 +413,14 @@ void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new);
#define sctp_stream_in(asoc, sid) (&(asoc)->stream.in[sid]) #define sctp_stream_in(asoc, sid) (&(asoc)->stream.in[sid])
/* What is the current MID_uo number for this stream? */
#define sctp_mid_uo_peek(stream, type, sid) \
((stream)->type[sid].mid_uo)
/* Return the next MID_uo number for this stream. */
#define sctp_mid_uo_next(stream, type, sid) \
((stream)->type[sid].mid_uo++)
/* /*
* Pointers to address related SCTP functions. * Pointers to address related SCTP functions.
* (i.e. things that depend on the address family.) * (i.e. things that depend on the address family.)
...@@ -1379,8 +1387,9 @@ struct sctp_stream_out { ...@@ -1379,8 +1387,9 @@ struct sctp_stream_out {
__u32 mid; __u32 mid;
__u16 ssn; __u16 ssn;
}; };
__u8 state; __u32 mid_uo;
struct sctp_stream_out_ext *ext; struct sctp_stream_out_ext *ext;
__u8 state;
}; };
struct sctp_stream_in { struct sctp_stream_in {
...@@ -1388,8 +1397,11 @@ struct sctp_stream_in { ...@@ -1388,8 +1397,11 @@ struct sctp_stream_in {
__u32 mid; __u32 mid;
__u16 ssn; __u16 ssn;
}; };
__u32 mid_uo;
__u32 fsn; __u32 fsn;
__u32 fsn_uo;
char pd_mode; char pd_mode;
char pd_mode_uo;
}; };
struct sctp_stream { struct sctp_stream {
......
...@@ -45,6 +45,7 @@ struct sctp_ulpq { ...@@ -45,6 +45,7 @@ struct sctp_ulpq {
char pd_mode; char pd_mode;
struct sctp_association *asoc; struct sctp_association *asoc;
struct sk_buff_head reasm; struct sk_buff_head reasm;
struct sk_buff_head reasm_uo;
struct sk_buff_head lobby; struct sk_buff_head lobby;
}; };
......
...@@ -201,6 +201,22 @@ static void sctp_for_each_tx_datachunk(struct sctp_association *asoc, ...@@ -201,6 +201,22 @@ static void sctp_for_each_tx_datachunk(struct sctp_association *asoc,
cb(chunk); cb(chunk);
} }
static void sctp_for_each_rx_skb(struct sctp_association *asoc, struct sock *sk,
void (*cb)(struct sk_buff *, struct sock *))
{
struct sk_buff *skb, *tmp;
sctp_skb_for_each(skb, &asoc->ulpq.lobby, tmp)
cb(skb, sk);
sctp_skb_for_each(skb, &asoc->ulpq.reasm, tmp)
cb(skb, sk);
sctp_skb_for_each(skb, &asoc->ulpq.reasm_uo, tmp)
cb(skb, sk);
}
/* Verify that this is a valid address. */ /* Verify that this is a valid address. */
static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
int len) int len)
...@@ -1554,6 +1570,7 @@ static void sctp_close(struct sock *sk, long timeout) ...@@ -1554,6 +1570,7 @@ static void sctp_close(struct sock *sk, long timeout)
if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) || if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) ||
!skb_queue_empty(&asoc->ulpq.reasm) || !skb_queue_empty(&asoc->ulpq.reasm) ||
!skb_queue_empty(&asoc->ulpq.reasm_uo) ||
(sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) { (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) {
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
...@@ -8495,11 +8512,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, ...@@ -8495,11 +8512,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
} }
sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) sctp_for_each_rx_skb(assoc, newsk, sctp_skb_set_owner_r_frag);
sctp_skb_set_owner_r_frag(skb, newsk);
sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp)
sctp_skb_set_owner_r_frag(skb, newsk);
/* Set the type of socket to indicate that it is peeled off from the /* Set the type of socket to indicate that it is peeled off from the
* original UDP-style socket or created with the accept() call on a * original UDP-style socket or created with the accept() call on a
......
This diff is collapsed.
...@@ -60,6 +60,7 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq, ...@@ -60,6 +60,7 @@ struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
ulpq->asoc = asoc; ulpq->asoc = asoc;
skb_queue_head_init(&ulpq->reasm); skb_queue_head_init(&ulpq->reasm);
skb_queue_head_init(&ulpq->reasm_uo);
skb_queue_head_init(&ulpq->lobby); skb_queue_head_init(&ulpq->lobby);
ulpq->pd_mode = 0; ulpq->pd_mode = 0;
...@@ -83,6 +84,10 @@ void sctp_ulpq_flush(struct sctp_ulpq *ulpq) ...@@ -83,6 +84,10 @@ void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
sctp_ulpevent_free(event); sctp_ulpevent_free(event);
} }
while ((skb = __skb_dequeue(&ulpq->reasm_uo)) != NULL) {
event = sctp_skb2event(skb);
sctp_ulpevent_free(event);
}
} }
/* Dispose of a ulpqueue. */ /* Dispose of a ulpqueue. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment