diff options
author | Michele Baldessari <michele@acksyn.org> | 2012-11-30 23:49:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-12-03 13:32:15 -0500 |
commit | 196d67593439b03088913227093e374235596e33 (patch) | |
tree | d8d1580673e3cf878d6db230bf86b71187bf3550 /net/sctp/socket.c | |
parent | 96070ae4d08eefe62ac534904ce21a01e1a5c9c4 (diff) |
sctp: Add support to per-association statistics via a new SCTP_GET_ASSOC_STATS call
The current SCTP stack is lacking a mechanism to have per association
statistics. This is an implementation modeled after OpenSolaris'
SCTP_GET_ASSOC_STATS.
Userspace part will follow on lksctp if/when there is a general ACK on
this.
V4:
- Move ipackets++ before q->immediate.func() for consistency reasons
- Move sctp_max_rto() at the end of sctp_transport_update_rto() to avoid
returning bogus RTO values
- return asoc->rto_min when max_obs_rto value has not changed
V3:
- Increase ictrlchunks in sctp_assoc_bh_rcv() as well
- Move ipackets++ to sctp_inq_push()
- return 0 when no rto updates took place since the last call
V2:
- Implement partial retrieval of stat struct to cope for future expansion
- Kill the rtxpackets counter as it cannot be precise anyway
- Rename outseqtsns to outofseqtsns to make it clearer that these are out
of sequence unexpected TSNs
- Move asoc->ipackets++ under a lock to avoid potential miscounts
- Fold asoc->opackets++ into the already existing asoc check
- Kill unneeded (q->asoc) test when increasing rtxchunks
- Do not count octrlchunks if sending failed (SCTP_XMIT_OK != 0)
- Don't count SHUTDOWNs as SACKs
- Move SCTP_GET_ASSOC_STATS to the private space API
- Adjust the len check in sctp_getsockopt_assoc_stats() to allow for
future struct growth
- Move association statistics in their own struct
- Update idupchunks when we send a SACK with dup TSNs
- return min_rto in max_rto when RTO has not changed. Also return the
transport when max_rto last changed.
Signed-off: Michele Baldessari <michele@acksyn.org>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index bc1624913c42..9e65758cb038 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -611,6 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
611 | 2*asoc->pathmtu, 4380)); | 611 | 2*asoc->pathmtu, 4380)); |
612 | trans->ssthresh = asoc->peer.i.a_rwnd; | 612 | trans->ssthresh = asoc->peer.i.a_rwnd; |
613 | trans->rto = asoc->rto_initial; | 613 | trans->rto = asoc->rto_initial; |
614 | sctp_max_rto(asoc, trans); | ||
614 | trans->rtt = trans->srtt = trans->rttvar = 0; | 615 | trans->rtt = trans->srtt = trans->rttvar = 0; |
615 | sctp_transport_route(trans, NULL, | 616 | sctp_transport_route(trans, NULL, |
616 | sctp_sk(asoc->base.sk)); | 617 | sctp_sk(asoc->base.sk)); |
@@ -5635,6 +5636,71 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk, | |||
5635 | return 0; | 5636 | return 0; |
5636 | } | 5637 | } |
5637 | 5638 | ||
5639 | /* | ||
5640 | * SCTP_GET_ASSOC_STATS | ||
5641 | * | ||
5642 | * This option retrieves local per endpoint statistics. It is modeled | ||
5643 | * after OpenSolaris' implementation | ||
5644 | */ | ||
5645 | static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, | ||
5646 | char __user *optval, | ||
5647 | int __user *optlen) | ||
5648 | { | ||
5649 | struct sctp_assoc_stats sas; | ||
5650 | struct sctp_association *asoc = NULL; | ||
5651 | |||
5652 | /* User must provide at least the assoc id */ | ||
5653 | if (len < sizeof(sctp_assoc_t)) | ||
5654 | return -EINVAL; | ||
5655 | |||
5656 | if (copy_from_user(&sas, optval, len)) | ||
5657 | return -EFAULT; | ||
5658 | |||
5659 | asoc = sctp_id2assoc(sk, sas.sas_assoc_id); | ||
5660 | if (!asoc) | ||
5661 | return -EINVAL; | ||
5662 | |||
5663 | sas.sas_rtxchunks = asoc->stats.rtxchunks; | ||
5664 | sas.sas_gapcnt = asoc->stats.gapcnt; | ||
5665 | sas.sas_outofseqtsns = asoc->stats.outofseqtsns; | ||
5666 | sas.sas_osacks = asoc->stats.osacks; | ||
5667 | sas.sas_isacks = asoc->stats.isacks; | ||
5668 | sas.sas_octrlchunks = asoc->stats.octrlchunks; | ||
5669 | sas.sas_ictrlchunks = asoc->stats.ictrlchunks; | ||
5670 | sas.sas_oodchunks = asoc->stats.oodchunks; | ||
5671 | sas.sas_iodchunks = asoc->stats.iodchunks; | ||
5672 | sas.sas_ouodchunks = asoc->stats.ouodchunks; | ||
5673 | sas.sas_iuodchunks = asoc->stats.iuodchunks; | ||
5674 | sas.sas_idupchunks = asoc->stats.idupchunks; | ||
5675 | sas.sas_opackets = asoc->stats.opackets; | ||
5676 | sas.sas_ipackets = asoc->stats.ipackets; | ||
5677 | |||
5678 | /* New high max rto observed, will return 0 if not a single | ||
5679 | * RTO update took place. obs_rto_ipaddr will be bogus | ||
5680 | * in such a case | ||
5681 | */ | ||
5682 | sas.sas_maxrto = asoc->stats.max_obs_rto; | ||
5683 | memcpy(&sas.sas_obs_rto_ipaddr, &asoc->stats.obs_rto_ipaddr, | ||
5684 | sizeof(struct sockaddr_storage)); | ||
5685 | |||
5686 | /* Mark beginning of a new observation period */ | ||
5687 | asoc->stats.max_obs_rto = asoc->rto_min; | ||
5688 | |||
5689 | /* Allow the struct to grow and fill in as much as possible */ | ||
5690 | len = min_t(size_t, len, sizeof(sas)); | ||
5691 | |||
5692 | if (put_user(len, optlen)) | ||
5693 | return -EFAULT; | ||
5694 | |||
5695 | SCTP_DEBUG_PRINTK("sctp_getsockopt_assoc_stat(%d): %d\n", | ||
5696 | len, sas.sas_assoc_id); | ||
5697 | |||
5698 | if (copy_to_user(optval, &sas, len)) | ||
5699 | return -EFAULT; | ||
5700 | |||
5701 | return 0; | ||
5702 | } | ||
5703 | |||
5638 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5704 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
5639 | char __user *optval, int __user *optlen) | 5705 | char __user *optval, int __user *optlen) |
5640 | { | 5706 | { |
@@ -5776,6 +5842,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5776 | case SCTP_PEER_ADDR_THLDS: | 5842 | case SCTP_PEER_ADDR_THLDS: |
5777 | retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen); | 5843 | retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen); |
5778 | break; | 5844 | break; |
5845 | case SCTP_GET_ASSOC_STATS: | ||
5846 | retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen); | ||
5847 | break; | ||
5779 | default: | 5848 | default: |
5780 | retval = -ENOPROTOOPT; | 5849 | retval = -ENOPROTOOPT; |
5781 | break; | 5850 | break; |