Commit 4cc42719 authored by Sridhar Samudrala's avatar Sridhar Samudrala

Merge us.ibm.com:/home/sridhar/BK/linux-2.5.56

into us.ibm.com:/home/sridhar/BK/lksctp-2.5.56
parents efa0596f ea5d287f
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
* Xingang Guo <xingang.guo@intel.com> * Xingang Guo <xingang.guo@intel.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -147,7 +148,9 @@ extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg); ...@@ -147,7 +148,9 @@ extern int sctp_primitive_REQUESTHEARTBEAT(sctp_association_t *, void *arg);
/* /*
* sctp_crc32c.c * sctp_crc32c.c
*/ */
extern __u32 count_crc(__u8 *ptr, __u16 count); extern __u32 sctp_start_cksum(__u8 *ptr, __u16 count);
extern __u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 cksum);
extern __u32 sctp_end_cksum(__u32 cksum);
/* /*
* sctp_input.c * sctp_input.c
......
...@@ -100,6 +100,14 @@ enum sctp_optname { ...@@ -100,6 +100,14 @@ enum sctp_optname {
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM #define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
SCTP_SOCKOPT_PEELOFF, /* peel off association. */ SCTP_SOCKOPT_PEELOFF, /* peel off association. */
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF #define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
SCTP_GET_PEER_ADDRS_NUM, /* Get number of peer addresss. */
#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM
SCTP_GET_PEER_ADDRS, /* Get all peer addresss. */
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
SCTP_GET_LOCAL_ADDRS_NUM, /* Get number of local addresss. */
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
}; };
...@@ -576,6 +584,15 @@ struct sctp_setstrm_timeout { ...@@ -576,6 +584,15 @@ struct sctp_setstrm_timeout {
__u16 ssto_streamid_end; __u16 ssto_streamid_end;
}; };
/*
* 8.3 8.5 get all peer/local addresses on a socket
* This parameter struct is for getsockopt
*/
struct sctp_getaddrs {
sctp_assoc_t assoc_id;
int addr_num;
struct sockaddr_storage *addrs;
};
/* These are bit fields for msghdr->msg_flags. See section 5.1. */ /* These are bit fields for msghdr->msg_flags. See section 5.1. */
/* On user space Linux, these live in <bits/socket.h> as an enum. */ /* On user space Linux, these live in <bits/socket.h> as an enum. */
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2003 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
* Randall Stewart <rstewar1@email.mot.com> * Randall Stewart <rstewar1@email.mot.com>
* Ken Morneau <kmorneau@cisco.com> * Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com> * Qiaobing Xie <qxie1@email.mot.com>
* Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -122,7 +124,7 @@ unsigned long update_adler32(unsigned long adler, ...@@ -122,7 +124,7 @@ unsigned long update_adler32(unsigned long adler,
return (s2 << 16) + s1; return (s2 << 16) + s1;
} }
__u32 count_crc(__u8 *ptr, __u16 count) __u32 sctp_start_cksum(__u8 *ptr, __u16 count)
{ {
/* /*
* Update a running Adler-32 checksum with the bytes * Update a running Adler-32 checksum with the bytes
...@@ -146,3 +148,15 @@ __u32 count_crc(__u8 *ptr, __u16 count) ...@@ -146,3 +148,15 @@ __u32 count_crc(__u8 *ptr, __u16 count)
return adler; return adler;
} }
__u32 sctp_update_cksum(__u8 *ptr, __u16 count, __u32 adler)
{
adler = update_adler32(adler, ptr, count);
return adler;
}
__u32 sctp_end_cksum(__u32 adler)
{
return adler;
}
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* Written or modified by: * Written or modified by:
* Dinakaran Joseph * Dinakaran Joseph
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Sridhar Samudrala <sri@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
...@@ -135,11 +136,10 @@ __u32 crc_c[256] = { ...@@ -135,11 +136,10 @@ __u32 crc_c[256] = {
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,
}; };
__u32 count_crc(__u8 *buffer, __u16 length) __u32 sctp_start_cksum(__u8 *buffer, __u16 length)
{ {
__u32 crc32 = ~(__u32) 0; __u32 crc32 = ~(__u32) 0;
__u32 i, result; __u32 i;
__u8 byte0, byte1, byte2, byte3;
/* Optimize this routine to be SCTP specific, knowing how /* Optimize this routine to be SCTP specific, knowing how
* to skip the checksum field of the SCTP header. * to skip the checksum field of the SCTP header.
...@@ -157,6 +157,24 @@ __u32 count_crc(__u8 *buffer, __u16 length) ...@@ -157,6 +157,24 @@ __u32 count_crc(__u8 *buffer, __u16 length)
for (i = sizeof(struct sctphdr); i < length ; i++) for (i = sizeof(struct sctphdr); i < length ; i++)
CRC32C(crc32, buffer[i]); CRC32C(crc32, buffer[i]);
return crc32;
}
__u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
{
__u32 i;
for (i = 0; i < length ; i++)
CRC32C(crc32, buffer[i]);
return crc32;
}
__u32 sctp_end_cksum(__u32 crc32)
{
__u32 result;
__u8 byte0, byte1, byte2, byte3;
result = ~crc32; result = ~crc32;
/* result now holds the negated polynomial remainder; /* result now holds the negated polynomial remainder;
...@@ -183,5 +201,3 @@ __u32 count_crc(__u8 *buffer, __u16 length) ...@@ -183,5 +201,3 @@ __u32 count_crc(__u8 *buffer, __u16 length)
byte3); byte3);
return crc32; return crc32;
} }
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
...@@ -72,10 +72,19 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb) ...@@ -72,10 +72,19 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb)
{ {
struct sctphdr *sh; struct sctphdr *sh;
__u32 cmp, val; __u32 cmp, val;
struct sk_buff *list = skb_shinfo(skb)->frag_list;
sh = (struct sctphdr *) skb->h.raw; sh = (struct sctphdr *) skb->h.raw;
cmp = ntohl(sh->checksum); cmp = ntohl(sh->checksum);
val = count_crc((__u8 *)sh, skb->len);
val = sctp_start_cksum((__u8 *)sh, skb_headlen(skb));
for (; list; list = list->next)
val = sctp_update_cksum((__u8 *)list->data, skb_headlen(list),
val);
val = sctp_end_cksum(val);
if (val != cmp) { if (val != cmp) {
/* CRC failure, dump it. */ /* CRC failure, dump it. */
return -1; return -1;
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
/* Forward declarations for private helpers. */ /* Forward declarations for private helpers. */
__u32 count_crc(__u8 *ptr, __u16 count);
static void sctp_packet_reset(sctp_packet_t *packet); static void sctp_packet_reset(sctp_packet_t *packet);
static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet, static sctp_xmit_t sctp_packet_append_data(sctp_packet_t *packet,
sctp_chunk_t *chunk); sctp_chunk_t *chunk);
...@@ -358,7 +357,8 @@ int sctp_packet_transmit(sctp_packet_t *packet) ...@@ -358,7 +357,8 @@ int sctp_packet_transmit(sctp_packet_t *packet)
* Note: Adler-32 is no longer applicable, as has been replaced * Note: Adler-32 is no longer applicable, as has been replaced
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>. * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
*/ */
crc32 = count_crc((__u8 *)sh, nskb->len); crc32 = sctp_start_cksum((__u8 *)sh, nskb->len);
crc32 = sctp_end_cksum(crc32);
/* 3) Put the resultant value into the checksum field in the /* 3) Put the resultant value into the checksum field in the
* common header, and leave the rest of the bits unchanged. * common header, and leave the rest of the bits unchanged.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001-2002 International Business Machines Corp. * Copyright (c) 2001-2003 International Business Machines Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
...@@ -230,7 +230,7 @@ void sctp_retransmit_insert(struct list_head *tlchunk, sctp_outqueue_t *q) ...@@ -230,7 +230,7 @@ void sctp_retransmit_insert(struct list_head *tlchunk, sctp_outqueue_t *q)
list_add_tail(tlchunk, &q->retransmit); list_add_tail(tlchunk, &q->retransmit);
} }
} }
/* Mark all the eligible packets on a transport for retransmission. */ /* Mark all the eligible packets on a transport for retransmission. */
void sctp_retransmit_mark(sctp_outqueue_t *q, sctp_transport_t *transport, void sctp_retransmit_mark(sctp_outqueue_t *q, sctp_transport_t *transport,
__u8 fast_retransmit) __u8 fast_retransmit)
...@@ -374,6 +374,18 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt, ...@@ -374,6 +374,18 @@ static int sctp_flush_retran_queue(sctp_outqueue_t *q, sctp_packet_t *pkt,
continue; continue;
} }
#endif #endif
/* Make sure that Gap Acked TSNs are not retransmitted. A
* simple approach is just to move such TSNs out of the
* way and into a 'transmitted' queue and skip to the
* next chunk.
*/
if (chunk->tsn_gap_acked) {
list_add_tail(lchunk, &transport->transmitted);
lchunk = sctp_list_dequeue(lqueue);
continue;
}
/* Attempt to append this chunk to the packet. */ /* Attempt to append this chunk to the packet. */
status = (*q->append_output)(pkt, chunk); status = (*q->append_output)(pkt, chunk);
...@@ -1028,7 +1040,7 @@ static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack, ...@@ -1028,7 +1040,7 @@ static __u32 sctp_highest_new_tsn(sctp_sackhdr_t *sack,
} }
return highest_new_tsn; return highest_new_tsn;
} }
/* This is where we REALLY process a SACK. /* This is where we REALLY process a SACK.
* *
...@@ -1053,7 +1065,7 @@ int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack) ...@@ -1053,7 +1065,7 @@ int sctp_sack_outqueue(sctp_outqueue_t *q, sctp_sackhdr_t *sack)
sack_ctsn = ntohl(sack->cum_tsn_ack); sack_ctsn = ntohl(sack->cum_tsn_ack);
/* Get the highest TSN in the sack. */ /* Get the highest TSN in the sack. */
highest_tsn = sack_ctsn + highest_tsn = sack_ctsn +
ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end); ntohs(frags[ntohs(sack->num_gap_ack_blocks) - 1].gab.end);
if (TSN_lt(asoc->highest_sacked, highest_tsn)) { if (TSN_lt(asoc->highest_sacked, highest_tsn)) {
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
#include <net/sctp/sctp.h> #include <net/sctp/sctp.h>
#include <net/sctp/sm.h> #include <net/sctp/sm.h>
sctp_sm_table_entry_t bug = { static sctp_sm_table_entry_t bug = {
.fn = sctp_sf_bug, .fn = sctp_sf_bug,
.name = "sctp_sf_bug" .name = "sctp_sf_bug"
}; };
......
This diff is collapsed.
...@@ -606,9 +606,9 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event( ...@@ -606,9 +606,9 @@ sctp_ulpevent_t *sctp_ulpevent_make_shutdown_event(
sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc, sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
sctp_chunk_t *chunk, int priority) sctp_chunk_t *chunk, int priority)
{ {
sctp_ulpevent_t *event; sctp_ulpevent_t *event, *levent;
struct sctp_sndrcvinfo *info; struct sctp_sndrcvinfo *info;
struct sk_buff *skb; struct sk_buff *skb, *list;
size_t padding, len; size_t padding, len;
/* Clone the original skb, sharing the data. */ /* Clone the original skb, sharing the data. */
...@@ -647,6 +647,16 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc, ...@@ -647,6 +647,16 @@ sctp_ulpevent_t *sctp_ulpevent_make_rcvmsg(sctp_association_t *asoc,
event->malloced = 1; event->malloced = 1;
for (list = skb_shinfo(skb)->frag_list; list; list = list->next) {
sctp_ulpevent_set_owner_r(list, asoc);
/* Initialize event with flags 0. */
levent = sctp_ulpevent_init(event, skb, 0);
if (!levent)
goto fail_init;
levent->malloced = 1;
}
info = (struct sctp_sndrcvinfo *) &event->sndrcvinfo; info = (struct sctp_sndrcvinfo *) &event->sndrcvinfo;
/* Sockets API Extensions for SCTP /* Sockets API Extensions for SCTP
...@@ -764,6 +774,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) ...@@ -764,6 +774,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
sctp_chunk_t *sack; sctp_chunk_t *sack;
struct timer_list *timer; struct timer_list *timer;
int skb_len = skb_headlen(skb);
/* Current stack structures assume that the rcv buffer is /* Current stack structures assume that the rcv buffer is
* per socket. For UDP style sockets this is not true as * per socket. For UDP style sockets this is not true as
...@@ -774,18 +785,18 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) ...@@ -774,18 +785,18 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
event = (sctp_ulpevent_t *) skb->cb; event = (sctp_ulpevent_t *) skb->cb;
asoc = event->asoc; asoc = event->asoc;
if (asoc->rwnd_over) { if (asoc->rwnd_over) {
if (asoc->rwnd_over >= skb->len) { if (asoc->rwnd_over >= skb_len) {
asoc->rwnd_over -= skb->len; asoc->rwnd_over -= skb_len;
} else { } else {
asoc->rwnd += (skb->len - asoc->rwnd_over); asoc->rwnd += (skb_len - asoc->rwnd_over);
asoc->rwnd_over = 0; asoc->rwnd_over = 0;
} }
} else { } else {
asoc->rwnd += skb->len; asoc->rwnd += skb_len;
} }
SCTP_DEBUG_PRINTK("rwnd increased by %d to (%u, %u) - %u\n", SCTP_DEBUG_PRINTK("rwnd increased by %d to (%u, %u) - %u\n",
skb->len, asoc->rwnd, asoc->rwnd_over, asoc->a_rwnd); skb_len, asoc->rwnd, asoc->rwnd_over, asoc->a_rwnd);
/* Send a window update SACK if the rwnd has increased by at least the /* Send a window update SACK if the rwnd has increased by at least the
* minimum of the association's PMTU and half of the receive buffer. * minimum of the association's PMTU and half of the receive buffer.
...@@ -824,6 +835,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb) ...@@ -824,6 +835,7 @@ static void sctp_rcvmsg_rfree(struct sk_buff *skb)
static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *asoc) static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *asoc)
{ {
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
int skb_len = skb_headlen(skb);
/* The current stack structures assume that the rcv buffer is /* The current stack structures assume that the rcv buffer is
* per socket. For UDP-style sockets this is not true as * per socket. For UDP-style sockets this is not true as
...@@ -840,14 +852,14 @@ static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *a ...@@ -840,14 +852,14 @@ static void sctp_ulpevent_set_owner_r(struct sk_buff *skb, sctp_association_t *a
SCTP_ASSERT(asoc->rwnd, "rwnd zero", return); SCTP_ASSERT(asoc->rwnd, "rwnd zero", return);
SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return); SCTP_ASSERT(!asoc->rwnd_over, "rwnd_over not zero", return);
if (asoc->rwnd >= skb->len) { if (asoc->rwnd >= skb_len) {
asoc->rwnd -= skb->len; asoc->rwnd -= skb_len;
} else { } else {
asoc->rwnd_over = skb->len - asoc->rwnd; asoc->rwnd_over = skb_len - asoc->rwnd;
asoc->rwnd = 0; asoc->rwnd = 0;
} }
SCTP_DEBUG_PRINTK("rwnd decreased by %d to (%u, %u)\n", SCTP_DEBUG_PRINTK("rwnd decreased by %d to (%u, %u)\n",
skb->len, asoc->rwnd, asoc->rwnd_over); skb_len, asoc->rwnd, asoc->rwnd_over);
} }
/* A simple destructor to give up the reference to the association. */ /* A simple destructor to give up the reference to the association. */
......
/* SCTP kernel reference Implementation /* SCTP kernel reference Implementation
* Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2000 Cisco, Inc.
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001-2002 International Business Machines, Corp. * Copyright (c) 2001-2003 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 Nokia, Inc.
* Copyright (c) 2001 La Monte H.P. Yarroll * Copyright (c) 2001 La Monte H.P. Yarroll
...@@ -233,23 +233,41 @@ static inline void sctp_ulpqueue_store_reasm(sctp_ulpqueue_t *ulpq, sctp_ulpeven ...@@ -233,23 +233,41 @@ static inline void sctp_ulpqueue_store_reasm(sctp_ulpqueue_t *ulpq, sctp_ulpeven
/* Helper function to return an event corresponding to the reassembled /* Helper function to return an event corresponding to the reassembled
* datagram. * datagram.
* This routine creates a re-assembled skb given the first and last skb's
* as stored in the reassembly queue. The skb's may be non-linear if the sctp
* payload was fragmented on the way and ip had to reassemble them.
* We add the rest of skb's to the first skb's fraglist.
*/ */
static inline sctp_ulpevent_t *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag) static inline sctp_ulpevent_t *sctp_make_reassembled_event(struct sk_buff *f_frag, struct sk_buff *l_frag)
{ {
struct sk_buff *pos; struct sk_buff *pos;
sctp_ulpevent_t *event; sctp_ulpevent_t *event;
struct sk_buff *pnext; struct sk_buff *pnext, *last;
struct sk_buff *list = skb_shinfo(f_frag)->frag_list;
/* Store the pointer to the 2nd skb */
pos = f_frag->next; pos = f_frag->next;
/* Set the first fragment's frag_list to point to the 2nd fragment. */ /* Get the last skb in the f_frag's frag_list if present. */
skb_shinfo(f_frag)->frag_list = pos; for (last = list; list; last = list,list = list->next);
/* Add the list of remaining fragments to the first fragments
* frag_list.
*/
if (last)
last->next = pos;
else
skb_shinfo(f_frag)->frag_list = pos;
/* Remove the first fragment from the reassembly queue. */ /* Remove the first fragment from the reassembly queue. */
__skb_unlink(f_frag, f_frag->list); __skb_unlink(f_frag, f_frag->list);
do { do {
pnext = pos->next; pnext = pos->next;
/* Update the len and data_len fields of the first fragment. */
f_frag->len += pos->len;
f_frag->data_len += pos->len;
/* Remove the fragment from the reassembly queue. */ /* Remove the fragment from the reassembly queue. */
__skb_unlink(pos, pos->list); __skb_unlink(pos, pos->list);
......
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