[CCID3]: Move the loss interval code to loss_interval.[ch]

And put this into net/dccp/ccids/lib/, where packet_history.[ch] will also be
moved and then we'll have a tfrc_lib.ko module that will be used by
dccp_ccid3.ko and other CCIDs that are variations of TFRC (RFC 3448).

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arnaldo Carvalho de Melo and committed by
David S. Miller
ae6706f0 cfc3c525

+234 -139
+1 -1
net/dccp/ccids/Makefile
··· 1 1 obj-$(CONFIG_IP_DCCP_CCID3) += dccp_ccid3.o 2 2 3 - dccp_ccid3-y := ccid3.o 3 + dccp_ccid3-y := ccid3.o lib/loss_interval.o
+27 -128
net/dccp/ccids/ccid3.c
··· 38 38 #include "../ccid.h" 39 39 #include "../dccp.h" 40 40 #include "../packet_history.h" 41 + #include "lib/loss_interval.h" 41 42 #include "ccid3.h" 42 43 43 44 /* ··· 63 62 64 63 static struct dccp_tx_hist *ccid3_tx_hist; 65 64 static struct dccp_rx_hist *ccid3_rx_hist; 66 - 67 - static kmem_cache_t *ccid3_loss_interval_hist_slab __read_mostly; 68 - 69 - static inline struct ccid3_loss_interval_hist_entry * 70 - ccid3_loss_interval_hist_entry_new(const unsigned int __nocast prio) 71 - { 72 - return kmem_cache_alloc(ccid3_loss_interval_hist_slab, prio); 73 - } 74 - 75 - static inline void ccid3_loss_interval_hist_entry_delete(struct ccid3_loss_interval_hist_entry *entry) 76 - { 77 - if (entry != NULL) 78 - kmem_cache_free(ccid3_loss_interval_hist_slab, entry); 79 - } 80 - 81 - static void ccid3_loss_interval_history_delete(struct list_head *hist) 82 - { 83 - struct ccid3_loss_interval_hist_entry *entry, *next; 84 - 85 - list_for_each_entry_safe(entry, next, hist, ccid3lih_node) { 86 - list_del_init(&entry->ccid3lih_node); 87 - kmem_cache_free(ccid3_loss_interval_hist_slab, entry); 88 - } 89 - } 65 + static struct dccp_li_hist *ccid3_li_hist; 90 66 91 67 static int ccid3_init(struct sock *sk) 92 68 { ··· 1392 1414 */ 1393 1415 num_later = TFRC_RECV_NUM_LATE_LOSS + 1; 1394 1416 1395 - if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { 1417 + if (!list_empty(&hcrx->ccid3hcrx_li_hist)) { 1396 1418 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, 1397 1419 dccphrx_node) { 1398 1420 if (num_later == 0) { ··· 1533 1555 &x_recv, sizeof(x_recv)); 1534 1556 } 1535 1557 1536 - /* Weights used to calculate loss event rate */ 1537 - /* 1538 - * These are integers as per section 8 of RFC3448. We can then divide by 4 * 1539 - * when we use it. 1540 - */ 1541 - static const int ccid3_hc_rx_w[TFRC_RECV_IVAL_F_LENGTH] = { 1542 - 4, 4, 4, 4, 3, 2, 1, 1, 1543 - }; 1544 - 1545 1558 /* 1546 1559 * args: fvalue - function value to match 1547 1560 * returns: p closest to that value ··· 1641 1672 { 1642 1673 struct dccp_sock *dp = dccp_sk(sk); 1643 1674 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1644 - struct ccid3_loss_interval_hist_entry *li_entry; 1645 1675 1646 - if (seq_loss != DCCP_MAX_SEQNO + 1) { 1647 - ccid3_pr_debug("%s, sk=%p, seq_loss=%llu, win_loss=%u, " 1648 - "packet loss detected\n", 1649 - dccp_role(sk), sk, seq_loss, win_loss); 1650 - 1651 - if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { 1652 - struct ccid3_loss_interval_hist_entry *li_tail = NULL; 1653 - int i; 1676 + if (seq_loss != DCCP_MAX_SEQNO + 1 && 1677 + list_empty(&hcrx->ccid3hcrx_li_hist)) { 1678 + struct dccp_li_hist_entry *li_tail; 1654 1679 1655 - ccid3_pr_debug("%s, sk=%p, first loss event detected, " 1656 - "creating history\n", 1657 - dccp_role(sk), sk); 1658 - for (i = 0; i <= TFRC_RECV_IVAL_F_LENGTH; ++i) { 1659 - li_entry = ccid3_loss_interval_hist_entry_new(SLAB_ATOMIC); 1660 - if (li_entry == NULL) { 1661 - ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist); 1662 - ccid3_pr_debug("%s, sk=%p, not enough " 1663 - "mem for creating " 1664 - "history\n", 1665 - dccp_role(sk), sk); 1666 - return; 1667 - } 1668 - if (li_tail == NULL) 1669 - li_tail = li_entry; 1670 - list_add(&li_entry->ccid3lih_node, 1671 - &hcrx->ccid3hcrx_loss_interval_hist); 1672 - } 1673 - 1674 - li_entry->ccid3lih_seqno = seq_loss; 1675 - li_entry->ccid3lih_win_count = win_loss; 1676 - 1677 - li_tail->ccid3lih_interval = ccid3_hc_rx_calc_first_li(sk); 1678 - } 1680 + li_tail = dccp_li_hist_interval_new(ccid3_li_hist, 1681 + &hcrx->ccid3hcrx_li_hist, 1682 + seq_loss, win_loss); 1683 + if (li_tail == NULL) 1684 + return; 1685 + li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); 1679 1686 } 1680 1687 /* FIXME: find end of interval */ 1681 1688 } ··· 1691 1746 } 1692 1747 1693 1748 if (a_loss == NULL) { 1694 - if (list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { 1749 + if (list_empty(&hcrx->ccid3hcrx_li_hist)) { 1695 1750 /* no loss event have occured yet */ 1696 - ccid3_pr_debug("%s, sk=%p, TODO: find a lost data " 1697 - "packet by comparing to initial " 1698 - "seqno\n", 1699 - dccp_role(sk), sk); 1751 + LIMIT_NETDEBUG("%s: TODO: find a lost data packet by " 1752 + "comparing to initial seqno\n", 1753 + dccp_role(sk)); 1700 1754 goto out_update_li; 1701 1755 } else { 1702 1756 pr_info("%s: %s, sk=%p, ERROR! Less than 4 data " ··· 1741 1797 1742 1798 out_update_li: 1743 1799 ccid3_hc_rx_update_li(sk, seq_loss, win_loss); 1744 - } 1745 - 1746 - static u32 ccid3_hc_rx_calc_i_mean(struct sock *sk) 1747 - { 1748 - struct dccp_sock *dp = dccp_sk(sk); 1749 - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1750 - struct ccid3_loss_interval_hist_entry *li_entry, *li_next; 1751 - int i = 0; 1752 - u32 i_tot; 1753 - u32 i_tot0 = 0; 1754 - u32 i_tot1 = 0; 1755 - u32 w_tot = 0; 1756 - 1757 - list_for_each_entry_safe(li_entry, li_next, 1758 - &hcrx->ccid3hcrx_loss_interval_hist, 1759 - ccid3lih_node) { 1760 - if (i < TFRC_RECV_IVAL_F_LENGTH) { 1761 - i_tot0 += li_entry->ccid3lih_interval * ccid3_hc_rx_w[i]; 1762 - w_tot += ccid3_hc_rx_w[i]; 1763 - } 1764 - 1765 - if (i != 0) 1766 - i_tot1 += li_entry->ccid3lih_interval * ccid3_hc_rx_w[i - 1]; 1767 - 1768 - if (++i > TFRC_RECV_IVAL_F_LENGTH) 1769 - break; 1770 - } 1771 - 1772 - if (i != TFRC_RECV_IVAL_F_LENGTH) { 1773 - pr_info("%s: %s, sk=%p, ERROR! Missing entry in " 1774 - "interval history!\n", 1775 - __FUNCTION__, dccp_role(sk), sk); 1776 - return 0; 1777 - } 1778 - 1779 - i_tot = max(i_tot0, i_tot1); 1780 - 1781 - /* FIXME: Why do we do this? -Ian McDonald */ 1782 - if (i_tot * 4 < w_tot) 1783 - i_tot = w_tot * 4; 1784 - 1785 - return i_tot * 4 / w_tot; 1786 1800 } 1787 1801 1788 1802 static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ··· 1841 1939 p_prev = hcrx->ccid3hcrx_p; 1842 1940 1843 1941 /* Calculate loss event rate */ 1844 - if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) 1942 + if (!list_empty(&hcrx->ccid3hcrx_li_hist)) 1845 1943 /* Scaling up by 1000000 as fixed decimal */ 1846 - hcrx->ccid3hcrx_p = 1000000 / ccid3_hc_rx_calc_i_mean(sk); 1944 + hcrx->ccid3hcrx_p = 1000000 / dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); 1847 1945 1848 1946 if (hcrx->ccid3hcrx_p > p_prev) { 1849 1947 ccid3_hc_rx_send_feedback(sk); ··· 1873 1971 1874 1972 hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; 1875 1973 INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); 1876 - INIT_LIST_HEAD(&hcrx->ccid3hcrx_loss_interval_hist); 1974 + INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); 1877 1975 /* 1878 1976 * XXX this seems to be paranoid, need to think more about this, for 1879 1977 * now start with something different than zero. -acme ··· 1898 1996 dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist); 1899 1997 1900 1998 /* Empty loss interval history */ 1901 - ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist); 1999 + dccp_li_hist_purge(ccid3_li_hist, &hcrx->ccid3hcrx_li_hist); 1902 2000 1903 2001 kfree(dp->dccps_hc_rx_ccid_private); 1904 2002 dp->dccps_hc_rx_ccid_private = NULL; ··· 1965 2063 if (ccid3_tx_hist == NULL) 1966 2064 goto out_free_rx; 1967 2065 1968 - ccid3_loss_interval_hist_slab = kmem_cache_create("li_hist_ccid3", 1969 - sizeof(struct ccid3_loss_interval_hist_entry), 1970 - 0, SLAB_HWCACHE_ALIGN, 1971 - NULL, NULL); 1972 - if (ccid3_loss_interval_hist_slab == NULL) 2066 + ccid3_li_hist = dccp_li_hist_new("ccid3"); 2067 + if (ccid3_li_hist == NULL) 1973 2068 goto out_free_tx; 1974 2069 1975 2070 rc = ccid_register(&ccid3); ··· 1976 2077 return rc; 1977 2078 1978 2079 out_free_loss_interval_history: 1979 - kmem_cache_destroy(ccid3_loss_interval_hist_slab); 1980 - ccid3_loss_interval_hist_slab = NULL; 2080 + dccp_li_hist_delete(ccid3_li_hist); 2081 + ccid3_li_hist = NULL; 1981 2082 out_free_tx: 1982 2083 dccp_tx_hist_delete(ccid3_tx_hist); 1983 2084 ccid3_tx_hist = NULL; ··· 2009 2110 dccp_rx_hist_delete(ccid3_rx_hist); 2010 2111 ccid3_rx_hist = NULL; 2011 2112 } 2012 - if (ccid3_loss_interval_hist_slab != NULL) { 2013 - kmem_cache_destroy(ccid3_loss_interval_hist_slab); 2014 - ccid3_loss_interval_hist_slab = NULL; 2113 + if (ccid3_li_hist != NULL) { 2114 + dccp_li_hist_delete(ccid3_li_hist); 2115 + ccid3_li_hist = NULL; 2015 2116 } 2016 2117 } 2017 2118 module_exit(ccid3_module_exit);
+1 -10
net/dccp/ccids/ccid3.h
··· 59 59 60 60 #define TFRC_SMALLEST_P 40 61 61 62 - #define TFRC_RECV_IVAL_F_LENGTH 8 63 - 64 62 /* Number of later packets received before one is considered lost */ 65 63 #define TFRC_RECV_NUM_LATE_LOSS 3 66 64 ··· 117 119 struct ccid3_options_received ccid3hctx_options_received; 118 120 }; 119 121 120 - struct ccid3_loss_interval_hist_entry { 121 - struct list_head ccid3lih_node; 122 - u64 ccid3lih_seqno:48, 123 - ccid3lih_win_count:4; 124 - u32 ccid3lih_interval; 125 - }; 126 - 127 122 struct ccid3_hc_rx_sock { 128 123 u64 ccid3hcrx_seqno_last_counter:48, 129 124 ccid3hcrx_state:8, ··· 127 136 struct timeval ccid3hcrx_tstamp_last_feedback; 128 137 struct timeval ccid3hcrx_tstamp_last_ack; 129 138 struct list_head ccid3hcrx_hist; 130 - struct list_head ccid3hcrx_loss_interval_hist; 139 + struct list_head ccid3hcrx_li_hist; 131 140 u16 ccid3hcrx_s; 132 141 u32 ccid3hcrx_pinv; 133 142 u32 ccid3hcrx_elapsed_time;
+144
net/dccp/ccids/lib/loss_interval.c
··· 1 + /* 2 + * net/dccp/ccids/lib/loss_interval.c 3 + * 4 + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 5 + * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> 6 + * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7 + * 8 + * This program is free software; you can redistribute it and/or modify 9 + * it under the terms of the GNU General Public License as published by 10 + * the Free Software Foundation; either version 2 of the License, or 11 + * (at your option) any later version. 12 + */ 13 + 14 + #include <linux/config.h> 15 + #include <linux/module.h> 16 + 17 + #include "loss_interval.h" 18 + 19 + struct dccp_li_hist *dccp_li_hist_new(const char *name) 20 + { 21 + struct dccp_li_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); 22 + static const char dccp_li_hist_mask[] = "li_hist_%s"; 23 + char *slab_name; 24 + 25 + if (hist == NULL) 26 + goto out; 27 + 28 + slab_name = kmalloc(strlen(name) + sizeof(dccp_li_hist_mask) - 1, 29 + GFP_ATOMIC); 30 + if (slab_name == NULL) 31 + goto out_free_hist; 32 + 33 + sprintf(slab_name, dccp_li_hist_mask, name); 34 + hist->dccplih_slab = kmem_cache_create(slab_name, 35 + sizeof(struct dccp_li_hist_entry), 36 + 0, SLAB_HWCACHE_ALIGN, 37 + NULL, NULL); 38 + if (hist->dccplih_slab == NULL) 39 + goto out_free_slab_name; 40 + out: 41 + return hist; 42 + out_free_slab_name: 43 + kfree(slab_name); 44 + out_free_hist: 45 + kfree(hist); 46 + hist = NULL; 47 + goto out; 48 + } 49 + 50 + EXPORT_SYMBOL_GPL(dccp_li_hist_new); 51 + 52 + void dccp_li_hist_delete(struct dccp_li_hist *hist) 53 + { 54 + const char* name = kmem_cache_name(hist->dccplih_slab); 55 + 56 + kmem_cache_destroy(hist->dccplih_slab); 57 + kfree(name); 58 + kfree(hist); 59 + } 60 + 61 + EXPORT_SYMBOL_GPL(dccp_li_hist_delete); 62 + 63 + void dccp_li_hist_purge(struct dccp_li_hist *hist, struct list_head *list) 64 + { 65 + struct dccp_li_hist_entry *entry, *next; 66 + 67 + list_for_each_entry_safe(entry, next, list, dccplih_node) { 68 + list_del_init(&entry->dccplih_node); 69 + kmem_cache_free(hist->dccplih_slab, entry); 70 + } 71 + } 72 + 73 + EXPORT_SYMBOL_GPL(dccp_li_hist_purge); 74 + 75 + /* Weights used to calculate loss event rate */ 76 + /* 77 + * These are integers as per section 8 of RFC3448. We can then divide by 4 * 78 + * when we use it. 79 + */ 80 + static const int dccp_li_hist_w[DCCP_LI_HIST_IVAL_F_LENGTH] = { 81 + 4, 4, 4, 4, 3, 2, 1, 1, 82 + }; 83 + 84 + u32 dccp_li_hist_calc_i_mean(struct list_head *list) 85 + { 86 + struct dccp_li_hist_entry *li_entry, *li_next; 87 + int i = 0; 88 + u32 i_tot; 89 + u32 i_tot0 = 0; 90 + u32 i_tot1 = 0; 91 + u32 w_tot = 0; 92 + 93 + list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) { 94 + if (i < DCCP_LI_HIST_IVAL_F_LENGTH) { 95 + i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i]; 96 + w_tot += dccp_li_hist_w[i]; 97 + } 98 + 99 + if (i != 0) 100 + i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1]; 101 + 102 + if (++i > DCCP_LI_HIST_IVAL_F_LENGTH) 103 + break; 104 + } 105 + 106 + if (i != DCCP_LI_HIST_IVAL_F_LENGTH) 107 + return 0; 108 + 109 + i_tot = max(i_tot0, i_tot1); 110 + 111 + /* FIXME: Why do we do this? -Ian McDonald */ 112 + if (i_tot * 4 < w_tot) 113 + i_tot = w_tot * 4; 114 + 115 + return i_tot * 4 / w_tot; 116 + } 117 + 118 + EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); 119 + 120 + struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist, 121 + struct list_head *list, 122 + const u64 seq_loss, 123 + const u8 win_loss) 124 + { 125 + struct dccp_li_hist_entry *tail = NULL, *entry; 126 + int i; 127 + 128 + for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) { 129 + entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); 130 + if (entry == NULL) { 131 + dccp_li_hist_purge(hist, list); 132 + return NULL; 133 + } 134 + if (tail == NULL) 135 + tail = entry; 136 + list_add(&entry->dccplih_node, list); 137 + } 138 + 139 + entry->dccplih_seqno = seq_loss; 140 + entry->dccplih_win_count = win_loss; 141 + return tail; 142 + } 143 + 144 + EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
+61
net/dccp/ccids/lib/loss_interval.h
··· 1 + #ifndef _DCCP_LI_HIST_ 2 + #define _DCCP_LI_HIST_ 3 + /* 4 + * net/dccp/ccids/lib/loss_interval.h 5 + * 6 + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 7 + * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> 8 + * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 9 + * 10 + * This program is free software; you can redistribute it and/or modify it 11 + * under the terms of the GNU General Public License as published by the Free 12 + * Software Foundation; either version 2 of the License, or (at your option) 13 + * any later version. 14 + */ 15 + 16 + #include <linux/config.h> 17 + #include <linux/list.h> 18 + #include <linux/slab.h> 19 + #include <linux/time.h> 20 + 21 + #define DCCP_LI_HIST_IVAL_F_LENGTH 8 22 + 23 + struct dccp_li_hist { 24 + kmem_cache_t *dccplih_slab; 25 + }; 26 + 27 + extern struct dccp_li_hist *dccp_li_hist_new(const char *name); 28 + extern void dccp_li_hist_delete(struct dccp_li_hist *hist); 29 + 30 + struct dccp_li_hist_entry { 31 + struct list_head dccplih_node; 32 + u64 dccplih_seqno:48, 33 + dccplih_win_count:4; 34 + u32 dccplih_interval; 35 + }; 36 + 37 + static inline struct dccp_li_hist_entry * 38 + dccp_li_hist_entry_new(struct dccp_li_hist *hist, 39 + const unsigned int __nocast prio) 40 + { 41 + return kmem_cache_alloc(hist->dccplih_slab, prio); 42 + } 43 + 44 + static inline void dccp_li_hist_entry_delete(struct dccp_li_hist *hist, 45 + struct dccp_li_hist_entry *entry) 46 + { 47 + if (entry != NULL) 48 + kmem_cache_free(hist->dccplih_slab, entry); 49 + } 50 + 51 + extern void dccp_li_hist_purge(struct dccp_li_hist *hist, 52 + struct list_head *list); 53 + 54 + extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); 55 + 56 + extern struct dccp_li_hist_entry * 57 + dccp_li_hist_interval_new(struct dccp_li_hist *hist, 58 + struct list_head *list, 59 + const u64 seq_loss, 60 + const u8 win_loss); 61 + #endif /* _DCCP_LI_HIST_ */