aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorMichele Baldessari <michele@acksyn.org>2012-11-30 23:49:42 -0500
committerDavid S. Miller <davem@davemloft.net>2012-12-03 13:32:15 -0500
commit196d67593439b03088913227093e374235596e33 (patch)
treed8d1580673e3cf878d6db230bf86b71187bf3550 /net/sctp/socket.c
parent96070ae4d08eefe62ac534904ce21a01e1a5c9c4 (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.c69
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 */
5645static 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
5638SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, 5704SCTP_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;