diff options
Diffstat (limited to 'net/dccp/ccids/ccid3.c')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 155 |
1 files changed, 27 insertions, 128 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index cfd11234d8f9..7468928b83c6 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "../ccid.h" | 38 | #include "../ccid.h" |
39 | #include "../dccp.h" | 39 | #include "../dccp.h" |
40 | #include "../packet_history.h" | 40 | #include "../packet_history.h" |
41 | #include "lib/loss_interval.h" | ||
41 | #include "ccid3.h" | 42 | #include "ccid3.h" |
42 | 43 | ||
43 | /* | 44 | /* |
@@ -62,30 +63,7 @@ static int ccid3_debug; | |||
62 | 63 | ||
63 | static struct dccp_tx_hist *ccid3_tx_hist; | 64 | static struct dccp_tx_hist *ccid3_tx_hist; |
64 | static struct dccp_rx_hist *ccid3_rx_hist; | 65 | static struct dccp_rx_hist *ccid3_rx_hist; |
65 | 66 | static struct dccp_li_hist *ccid3_li_hist; | |
66 | static kmem_cache_t *ccid3_loss_interval_hist_slab __read_mostly; | ||
67 | |||
68 | static inline struct ccid3_loss_interval_hist_entry * | ||
69 | ccid3_loss_interval_hist_entry_new(const unsigned int __nocast prio) | ||
70 | { | ||
71 | return kmem_cache_alloc(ccid3_loss_interval_hist_slab, prio); | ||
72 | } | ||
73 | |||
74 | static inline void ccid3_loss_interval_hist_entry_delete(struct ccid3_loss_interval_hist_entry *entry) | ||
75 | { | ||
76 | if (entry != NULL) | ||
77 | kmem_cache_free(ccid3_loss_interval_hist_slab, entry); | ||
78 | } | ||
79 | |||
80 | static void ccid3_loss_interval_history_delete(struct list_head *hist) | ||
81 | { | ||
82 | struct ccid3_loss_interval_hist_entry *entry, *next; | ||
83 | |||
84 | list_for_each_entry_safe(entry, next, hist, ccid3lih_node) { | ||
85 | list_del_init(&entry->ccid3lih_node); | ||
86 | kmem_cache_free(ccid3_loss_interval_hist_slab, entry); | ||
87 | } | ||
88 | } | ||
89 | 67 | ||
90 | static int ccid3_init(struct sock *sk) | 68 | static int ccid3_init(struct sock *sk) |
91 | { | 69 | { |
@@ -1414,7 +1392,7 @@ trim_history: | |||
1414 | */ | 1392 | */ |
1415 | num_later = TFRC_RECV_NUM_LATE_LOSS + 1; | 1393 | num_later = TFRC_RECV_NUM_LATE_LOSS + 1; |
1416 | 1394 | ||
1417 | if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { | 1395 | if (!list_empty(&hcrx->ccid3hcrx_li_hist)) { |
1418 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, | 1396 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, |
1419 | dccphrx_node) { | 1397 | dccphrx_node) { |
1420 | if (num_later == 0) { | 1398 | if (num_later == 0) { |
@@ -1555,15 +1533,6 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) | |||
1555 | &x_recv, sizeof(x_recv)); | 1533 | &x_recv, sizeof(x_recv)); |
1556 | } | 1534 | } |
1557 | 1535 | ||
1558 | /* Weights used to calculate loss event rate */ | ||
1559 | /* | ||
1560 | * These are integers as per section 8 of RFC3448. We can then divide by 4 * | ||
1561 | * when we use it. | ||
1562 | */ | ||
1563 | static const int ccid3_hc_rx_w[TFRC_RECV_IVAL_F_LENGTH] = { | ||
1564 | 4, 4, 4, 4, 3, 2, 1, 1, | ||
1565 | }; | ||
1566 | |||
1567 | /* | 1536 | /* |
1568 | * args: fvalue - function value to match | 1537 | * args: fvalue - function value to match |
1569 | * returns: p closest to that value | 1538 | * returns: p closest to that value |
@@ -1672,41 +1641,17 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) | |||
1672 | { | 1641 | { |
1673 | struct dccp_sock *dp = dccp_sk(sk); | 1642 | struct dccp_sock *dp = dccp_sk(sk); |
1674 | struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; | 1643 | struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; |
1675 | struct ccid3_loss_interval_hist_entry *li_entry; | ||
1676 | 1644 | ||
1677 | if (seq_loss != DCCP_MAX_SEQNO + 1) { | 1645 | if (seq_loss != DCCP_MAX_SEQNO + 1 && |
1678 | ccid3_pr_debug("%s, sk=%p, seq_loss=%llu, win_loss=%u, " | 1646 | list_empty(&hcrx->ccid3hcrx_li_hist)) { |
1679 | "packet loss detected\n", | 1647 | struct dccp_li_hist_entry *li_tail; |
1680 | dccp_role(sk), sk, seq_loss, win_loss); | ||
1681 | |||
1682 | if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { | ||
1683 | struct ccid3_loss_interval_hist_entry *li_tail = NULL; | ||
1684 | int i; | ||
1685 | |||
1686 | ccid3_pr_debug("%s, sk=%p, first loss event detected, " | ||
1687 | "creating history\n", | ||
1688 | dccp_role(sk), sk); | ||
1689 | for (i = 0; i <= TFRC_RECV_IVAL_F_LENGTH; ++i) { | ||
1690 | li_entry = ccid3_loss_interval_hist_entry_new(SLAB_ATOMIC); | ||
1691 | if (li_entry == NULL) { | ||
1692 | ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist); | ||
1693 | ccid3_pr_debug("%s, sk=%p, not enough " | ||
1694 | "mem for creating " | ||
1695 | "history\n", | ||
1696 | dccp_role(sk), sk); | ||
1697 | return; | ||
1698 | } | ||
1699 | if (li_tail == NULL) | ||
1700 | li_tail = li_entry; | ||
1701 | list_add(&li_entry->ccid3lih_node, | ||
1702 | &hcrx->ccid3hcrx_loss_interval_hist); | ||
1703 | } | ||
1704 | 1648 | ||
1705 | li_entry->ccid3lih_seqno = seq_loss; | 1649 | li_tail = dccp_li_hist_interval_new(ccid3_li_hist, |
1706 | li_entry->ccid3lih_win_count = win_loss; | 1650 | &hcrx->ccid3hcrx_li_hist, |
1707 | 1651 | seq_loss, win_loss); | |
1708 | li_tail->ccid3lih_interval = ccid3_hc_rx_calc_first_li(sk); | 1652 | if (li_tail == NULL) |
1709 | } | 1653 | return; |
1654 | li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); | ||
1710 | } | 1655 | } |
1711 | /* FIXME: find end of interval */ | 1656 | /* FIXME: find end of interval */ |
1712 | } | 1657 | } |
@@ -1746,12 +1691,11 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk) | |||
1746 | } | 1691 | } |
1747 | 1692 | ||
1748 | if (a_loss == NULL) { | 1693 | if (a_loss == NULL) { |
1749 | if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { | 1694 | if (list_empty(&hcrx->ccid3hcrx_li_hist)) { |
1750 | /* no loss event have occured yet */ | 1695 | /* no loss event have occured yet */ |
1751 | ccid3_pr_debug("%s, sk=%p, TODO: find a lost data " | 1696 | LIMIT_NETDEBUG("%s: TODO: find a lost data packet by " |
1752 | "packet by comparing to initial " | 1697 | "comparing to initial seqno\n", |
1753 | "seqno\n", | 1698 | dccp_role(sk)); |
1754 | dccp_role(sk), sk); | ||
1755 | goto out_update_li; | 1699 | goto out_update_li; |
1756 | } else { | 1700 | } else { |
1757 | pr_info("%s: %s, sk=%p, ERROR! Less than 4 data " | 1701 | pr_info("%s: %s, sk=%p, ERROR! Less than 4 data " |
@@ -1799,48 +1743,6 @@ out_update_li: | |||
1799 | ccid3_hc_rx_update_li(sk, seq_loss, win_loss); | 1743 | ccid3_hc_rx_update_li(sk, seq_loss, win_loss); |
1800 | } | 1744 | } |
1801 | 1745 | ||
1802 | static u32 ccid3_hc_rx_calc_i_mean(struct sock *sk) | ||
1803 | { | ||
1804 | struct dccp_sock *dp = dccp_sk(sk); | ||
1805 | struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; | ||
1806 | struct ccid3_loss_interval_hist_entry *li_entry, *li_next; | ||
1807 | int i = 0; | ||
1808 | u32 i_tot; | ||
1809 | u32 i_tot0 = 0; | ||
1810 | u32 i_tot1 = 0; | ||
1811 | u32 w_tot = 0; | ||
1812 | |||
1813 | list_for_each_entry_safe(li_entry, li_next, | ||
1814 | &hcrx->ccid3hcrx_loss_interval_hist, | ||
1815 | ccid3lih_node) { | ||
1816 | if (i < TFRC_RECV_IVAL_F_LENGTH) { | ||
1817 | i_tot0 += li_entry->ccid3lih_interval * ccid3_hc_rx_w[i]; | ||
1818 | w_tot += ccid3_hc_rx_w[i]; | ||
1819 | } | ||
1820 | |||
1821 | if (i != 0) | ||
1822 | i_tot1 += li_entry->ccid3lih_interval * ccid3_hc_rx_w[i - 1]; | ||
1823 | |||
1824 | if (++i > TFRC_RECV_IVAL_F_LENGTH) | ||
1825 | break; | ||
1826 | } | ||
1827 | |||
1828 | if (i != TFRC_RECV_IVAL_F_LENGTH) { | ||
1829 | pr_info("%s: %s, sk=%p, ERROR! Missing entry in " | ||
1830 | "interval history!\n", | ||
1831 | __FUNCTION__, dccp_role(sk), sk); | ||
1832 | return 0; | ||
1833 | } | ||
1834 | |||
1835 | i_tot = max(i_tot0, i_tot1); | ||
1836 | |||
1837 | /* FIXME: Why do we do this? -Ian McDonald */ | ||
1838 | if (i_tot * 4 < w_tot) | ||
1839 | i_tot = w_tot * 4; | ||
1840 | |||
1841 | return i_tot * 4 / w_tot; | ||
1842 | } | ||
1843 | |||
1844 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | 1746 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) |
1845 | { | 1747 | { |
1846 | struct dccp_sock *dp = dccp_sk(sk); | 1748 | struct dccp_sock *dp = dccp_sk(sk); |
@@ -1939,9 +1841,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1939 | p_prev = hcrx->ccid3hcrx_p; | 1841 | p_prev = hcrx->ccid3hcrx_p; |
1940 | 1842 | ||
1941 | /* Calculate loss event rate */ | 1843 | /* Calculate loss event rate */ |
1942 | if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) | 1844 | if (!list_empty(&hcrx->ccid3hcrx_li_hist)) |
1943 | /* Scaling up by 1000000 as fixed decimal */ | 1845 | /* Scaling up by 1000000 as fixed decimal */ |
1944 | hcrx->ccid3hcrx_p = 1000000 / ccid3_hc_rx_calc_i_mean(sk); | 1846 | hcrx->ccid3hcrx_p = 1000000 / dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); |
1945 | 1847 | ||
1946 | if (hcrx->ccid3hcrx_p > p_prev) { | 1848 | if (hcrx->ccid3hcrx_p > p_prev) { |
1947 | ccid3_hc_rx_send_feedback(sk); | 1849 | ccid3_hc_rx_send_feedback(sk); |
@@ -1971,7 +1873,7 @@ static int ccid3_hc_rx_init(struct sock *sk) | |||
1971 | 1873 | ||
1972 | hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; | 1874 | hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; |
1973 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); | 1875 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); |
1974 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_loss_interval_hist); | 1876 | INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); |
1975 | /* | 1877 | /* |
1976 | * XXX this seems to be paranoid, need to think more about this, for | 1878 | * XXX this seems to be paranoid, need to think more about this, for |
1977 | * now start with something different than zero. -acme | 1879 | * now start with something different than zero. -acme |
@@ -1996,7 +1898,7 @@ static void ccid3_hc_rx_exit(struct sock *sk) | |||
1996 | dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist); | 1898 | dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist); |
1997 | 1899 | ||
1998 | /* Empty loss interval history */ | 1900 | /* Empty loss interval history */ |
1999 | ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist); | 1901 | dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); |
2000 | 1902 | ||
2001 | kfree(dp->dccps_hc_rx_ccid_private); | 1903 | kfree(dp->dccps_hc_rx_ccid_private); |
2002 | dp->dccps_hc_rx_ccid_private = NULL; | 1904 | dp->dccps_hc_rx_ccid_private = NULL; |
@@ -2063,11 +1965,8 @@ static __init int ccid3_module_init(void) | |||
2063 | if (ccid3_tx_hist == NULL) | 1965 | if (ccid3_tx_hist == NULL) |
2064 | goto out_free_rx; | 1966 | goto out_free_rx; |
2065 | 1967 | ||
2066 | ccid3_loss_interval_hist_slab = kmem_cache_create("li_hist_ccid3", | 1968 | ccid3_li_hist = dccp_li_hist_new("ccid3"); |
2067 | sizeof(struct ccid3_loss_interval_hist_entry), | 1969 | if (ccid3_li_hist == NULL) |
2068 | 0, SLAB_HWCACHE_ALIGN, | ||
2069 | NULL, NULL); | ||
2070 | if (ccid3_loss_interval_hist_slab == NULL) | ||
2071 | goto out_free_tx; | 1970 | goto out_free_tx; |
2072 | 1971 | ||
2073 | rc = ccid_register(&ccid3); | 1972 | rc = ccid_register(&ccid3); |
@@ -2077,8 +1976,8 @@ out: | |||
2077 | return rc; | 1976 | return rc; |
2078 | 1977 | ||
2079 | out_free_loss_interval_history: | 1978 | out_free_loss_interval_history: |
2080 | kmem_cache_destroy(ccid3_loss_interval_hist_slab); | 1979 | dccp_li_hist_delete(ccid3_li_hist); |
2081 | ccid3_loss_interval_hist_slab = NULL; | 1980 | ccid3_li_hist = NULL; |
2082 | out_free_tx: | 1981 | out_free_tx: |
2083 | dccp_tx_hist_delete(ccid3_tx_hist); | 1982 | dccp_tx_hist_delete(ccid3_tx_hist); |
2084 | ccid3_tx_hist = NULL; | 1983 | ccid3_tx_hist = NULL; |
@@ -2110,9 +2009,9 @@ static __exit void ccid3_module_exit(void) | |||
2110 | dccp_rx_hist_delete(ccid3_rx_hist); | 2009 | dccp_rx_hist_delete(ccid3_rx_hist); |
2111 | ccid3_rx_hist = NULL; | 2010 | ccid3_rx_hist = NULL; |
2112 | } | 2011 | } |
2113 | if (ccid3_loss_interval_hist_slab != NULL) { | 2012 | if (ccid3_li_hist != NULL) { |
2114 | kmem_cache_destroy(ccid3_loss_interval_hist_slab); | 2013 | dccp_li_hist_delete(ccid3_li_hist); |
2115 | ccid3_loss_interval_hist_slab = NULL; | 2014 | ccid3_li_hist = NULL; |
2116 | } | 2015 | } |
2117 | } | 2016 | } |
2118 | module_exit(ccid3_module_exit); | 2017 | module_exit(ccid3_module_exit); |