diff options
| -rw-r--r-- | include/net/sctp/structs.h | 4 | ||||
| -rw-r--r-- | include/net/sctp/tsnmap.h | 3 | ||||
| -rw-r--r-- | net/sctp/associola.c | 1 | ||||
| -rw-r--r-- | net/sctp/output.c | 5 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 16 | ||||
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 2 | ||||
| -rw-r--r-- | net/sctp/transport.c | 2 | ||||
| -rw-r--r-- | net/sctp/tsnmap.c | 6 | ||||
| -rw-r--r-- | net/sctp/ulpevent.c | 3 | ||||
| -rw-r--r-- | net/sctp/ulpqueue.c | 2 |
10 files changed, 39 insertions, 5 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index e4652fe58958..fecdf31816f2 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -912,6 +912,9 @@ struct sctp_transport { | |||
| 912 | /* Is this structure kfree()able? */ | 912 | /* Is this structure kfree()able? */ |
| 913 | malloced:1; | 913 | malloced:1; |
| 914 | 914 | ||
| 915 | /* Has this transport moved the ctsn since we last sacked */ | ||
| 916 | __u32 sack_generation; | ||
| 917 | |||
| 915 | struct flowi fl; | 918 | struct flowi fl; |
| 916 | 919 | ||
| 917 | /* This is the peer's IP address and port. */ | 920 | /* This is the peer's IP address and port. */ |
| @@ -1584,6 +1587,7 @@ struct sctp_association { | |||
| 1584 | */ | 1587 | */ |
| 1585 | __u8 sack_needed; /* Do we need to sack the peer? */ | 1588 | __u8 sack_needed; /* Do we need to sack the peer? */ |
| 1586 | __u32 sack_cnt; | 1589 | __u32 sack_cnt; |
| 1590 | __u32 sack_generation; | ||
| 1587 | 1591 | ||
| 1588 | /* These are capabilities which our peer advertised. */ | 1592 | /* These are capabilities which our peer advertised. */ |
| 1589 | __u8 ecn_capable:1, /* Can peer do ECN? */ | 1593 | __u8 ecn_capable:1, /* Can peer do ECN? */ |
diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h index e7728bc14ccf..2c5d2b4d5d1e 100644 --- a/include/net/sctp/tsnmap.h +++ b/include/net/sctp/tsnmap.h | |||
| @@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map); | |||
| 117 | int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn); | 117 | int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn); |
| 118 | 118 | ||
| 119 | /* Mark this TSN as seen. */ | 119 | /* Mark this TSN as seen. */ |
| 120 | int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn); | 120 | int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn, |
| 121 | struct sctp_transport *trans); | ||
| 121 | 122 | ||
| 122 | /* Mark this TSN and all lower as seen. */ | 123 | /* Mark this TSN and all lower as seen. */ |
| 123 | void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn); | 124 | void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5bc9ab161b37..b16517ee1aaf 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -271,6 +271,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 271 | */ | 271 | */ |
| 272 | asoc->peer.sack_needed = 1; | 272 | asoc->peer.sack_needed = 1; |
| 273 | asoc->peer.sack_cnt = 0; | 273 | asoc->peer.sack_cnt = 0; |
| 274 | asoc->peer.sack_generation = 1; | ||
| 274 | 275 | ||
| 275 | /* Assume that the peer will tell us if he recognizes ASCONF | 276 | /* Assume that the peer will tell us if he recognizes ASCONF |
| 276 | * as part of INIT exchange. | 277 | * as part of INIT exchange. |
diff --git a/net/sctp/output.c b/net/sctp/output.c index f1b7d4bb591e..6ae47acaaec6 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
| @@ -248,6 +248,11 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, | |||
| 248 | /* If the SACK timer is running, we have a pending SACK */ | 248 | /* If the SACK timer is running, we have a pending SACK */ |
| 249 | if (timer_pending(timer)) { | 249 | if (timer_pending(timer)) { |
| 250 | struct sctp_chunk *sack; | 250 | struct sctp_chunk *sack; |
| 251 | |||
| 252 | if (pkt->transport->sack_generation != | ||
| 253 | pkt->transport->asoc->peer.sack_generation) | ||
| 254 | return retval; | ||
| 255 | |||
| 251 | asoc->a_rwnd = asoc->rwnd; | 256 | asoc->a_rwnd = asoc->rwnd; |
| 252 | sack = sctp_make_sack(asoc); | 257 | sack = sctp_make_sack(asoc); |
| 253 | if (sack) { | 258 | if (sack) { |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index a85eeeb55dd0..b6de71efb140 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -734,8 +734,10 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
| 734 | int len; | 734 | int len; |
| 735 | __u32 ctsn; | 735 | __u32 ctsn; |
| 736 | __u16 num_gabs, num_dup_tsns; | 736 | __u16 num_gabs, num_dup_tsns; |
| 737 | struct sctp_association *aptr = (struct sctp_association *)asoc; | ||
| 737 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; | 738 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; |
| 738 | struct sctp_gap_ack_block gabs[SCTP_MAX_GABS]; | 739 | struct sctp_gap_ack_block gabs[SCTP_MAX_GABS]; |
| 740 | struct sctp_transport *trans; | ||
| 739 | 741 | ||
| 740 | memset(gabs, 0, sizeof(gabs)); | 742 | memset(gabs, 0, sizeof(gabs)); |
| 741 | ctsn = sctp_tsnmap_get_ctsn(map); | 743 | ctsn = sctp_tsnmap_get_ctsn(map); |
| @@ -805,6 +807,20 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) | |||
| 805 | sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns, | 807 | sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns, |
| 806 | sctp_tsnmap_get_dups(map)); | 808 | sctp_tsnmap_get_dups(map)); |
| 807 | 809 | ||
| 810 | /* Once we have a sack generated, check to see what our sack | ||
| 811 | * generation is, if its 0, reset the transports to 0, and reset | ||
| 812 | * the association generation to 1 | ||
| 813 | * | ||
| 814 | * The idea is that zero is never used as a valid generation for the | ||
| 815 | * association so no transport will match after a wrap event like this, | ||
| 816 | * Until the next sack | ||
| 817 | */ | ||
| 818 | if (++aptr->peer.sack_generation == 0) { | ||
| 819 | list_for_each_entry(trans, &asoc->peer.transport_addr_list, | ||
| 820 | transports) | ||
| 821 | trans->sack_generation = 0; | ||
| 822 | aptr->peer.sack_generation = 1; | ||
| 823 | } | ||
| 808 | nodata: | 824 | nodata: |
| 809 | return retval; | 825 | return retval; |
| 810 | } | 826 | } |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index c96d1a81cf42..8716da1a8592 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -1268,7 +1268,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1268 | case SCTP_CMD_REPORT_TSN: | 1268 | case SCTP_CMD_REPORT_TSN: |
| 1269 | /* Record the arrival of a TSN. */ | 1269 | /* Record the arrival of a TSN. */ |
| 1270 | error = sctp_tsnmap_mark(&asoc->peer.tsn_map, | 1270 | error = sctp_tsnmap_mark(&asoc->peer.tsn_map, |
| 1271 | cmd->obj.u32); | 1271 | cmd->obj.u32, NULL); |
| 1272 | break; | 1272 | break; |
| 1273 | 1273 | ||
| 1274 | case SCTP_CMD_REPORT_FWDTSN: | 1274 | case SCTP_CMD_REPORT_FWDTSN: |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index b026ba0c6992..1dcceb6e0ce6 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -68,6 +68,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 68 | peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); | 68 | peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); |
| 69 | memset(&peer->saddr, 0, sizeof(union sctp_addr)); | 69 | memset(&peer->saddr, 0, sizeof(union sctp_addr)); |
| 70 | 70 | ||
| 71 | peer->sack_generation = 0; | ||
| 72 | |||
| 71 | /* From 6.3.1 RTO Calculation: | 73 | /* From 6.3.1 RTO Calculation: |
| 72 | * | 74 | * |
| 73 | * C1) Until an RTT measurement has been made for a packet sent to the | 75 | * C1) Until an RTT measurement has been made for a packet sent to the |
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index f1e40cebc981..b5fb7c409023 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c | |||
| @@ -114,7 +114,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn) | |||
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | /* Mark this TSN as seen. */ | 116 | /* Mark this TSN as seen. */ |
| 117 | int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) | 117 | int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, |
| 118 | struct sctp_transport *trans) | ||
| 118 | { | 119 | { |
| 119 | u16 gap; | 120 | u16 gap; |
| 120 | 121 | ||
| @@ -133,6 +134,9 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) | |||
| 133 | */ | 134 | */ |
| 134 | map->max_tsn_seen++; | 135 | map->max_tsn_seen++; |
| 135 | map->cumulative_tsn_ack_point++; | 136 | map->cumulative_tsn_ack_point++; |
| 137 | if (trans) | ||
| 138 | trans->sack_generation = | ||
| 139 | trans->asoc->peer.sack_generation; | ||
| 136 | map->base_tsn++; | 140 | map->base_tsn++; |
| 137 | } else { | 141 | } else { |
| 138 | /* Either we already have a gap, or about to record a gap, so | 142 | /* Either we already have a gap, or about to record a gap, so |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 8a84017834c2..33d894776192 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
| @@ -715,7 +715,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, | |||
| 715 | * can mark it as received so the tsn_map is updated correctly. | 715 | * can mark it as received so the tsn_map is updated correctly. |
| 716 | */ | 716 | */ |
| 717 | if (sctp_tsnmap_mark(&asoc->peer.tsn_map, | 717 | if (sctp_tsnmap_mark(&asoc->peer.tsn_map, |
| 718 | ntohl(chunk->subh.data_hdr->tsn))) | 718 | ntohl(chunk->subh.data_hdr->tsn), |
| 719 | chunk->transport)) | ||
| 719 | goto fail_mark; | 720 | goto fail_mark; |
| 720 | 721 | ||
| 721 | /* First calculate the padding, so we don't inadvertently | 722 | /* First calculate the padding, so we don't inadvertently |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index f2d1de7f2ffb..f5a6a4f4faf7 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
| @@ -1051,7 +1051,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, | |||
| 1051 | if (chunk && (freed >= needed)) { | 1051 | if (chunk && (freed >= needed)) { |
| 1052 | __u32 tsn; | 1052 | __u32 tsn; |
| 1053 | tsn = ntohl(chunk->subh.data_hdr->tsn); | 1053 | tsn = ntohl(chunk->subh.data_hdr->tsn); |
| 1054 | sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn); | 1054 | sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport); |
| 1055 | sctp_ulpq_tail_data(ulpq, chunk, gfp); | 1055 | sctp_ulpq_tail_data(ulpq, chunk, gfp); |
| 1056 | 1056 | ||
| 1057 | sctp_ulpq_partial_delivery(ulpq, chunk, gfp); | 1057 | sctp_ulpq_partial_delivery(ulpq, chunk, gfp); |
