Deleted Added
full compact
ieee80211_node.c (172229) ieee80211_node.c (173273)
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_node.c 172229 2007-09-18 21:01:04Z sam $");
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_node.c 173273 2007-11-02 05:22:25Z sam $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/mbuf.h>
33#include <sys/malloc.h>
34#include <sys/kernel.h>
35
36#include <sys/socket.h>

--- 494 unchanged lines hidden (view full) ---

531 ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
532 ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
533 ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
534 );
535 return ieee80211_sta_join1(ieee80211_ref_node(ni));
536}
537
538/*
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/mbuf.h>
33#include <sys/malloc.h>
34#include <sys/kernel.h>
35
36#include <sys/socket.h>

--- 494 unchanged lines hidden (view full) ---

531 ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
532 ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
533 ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
534 );
535 return ieee80211_sta_join1(ieee80211_ref_node(ni));
536}
537
538/*
539 * Change the bss channel.
540 */
541void
542ieee80211_setbsschan(struct ieee80211com *ic, struct ieee80211_channel *c)
543{
544 ic->ic_bsschan = c;
545 ic->ic_curchan = ic->ic_bsschan;
546 ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
547 ic->ic_set_channel(ic);
548}
549
550/*
539 * Join the specified IBSS/BSS network. The node is assumed to
540 * be passed in with a held reference.
541 */
542static int
543ieee80211_sta_join1(struct ieee80211_node *selbs)
544{
545 struct ieee80211com *ic = selbs->ni_ic;
546 struct ieee80211_node *obss;

--- 32 unchanged lines hidden (view full) ---

579
580 /*
581 * Delete unusable rates; we've already checked
582 * that the negotiated rate set is acceptable.
583 */
584 ieee80211_fix_rate(ic->ic_bss, &ic->ic_bss->ni_rates,
585 IEEE80211_F_DODEL | IEEE80211_F_JOIN);
586
551 * Join the specified IBSS/BSS network. The node is assumed to
552 * be passed in with a held reference.
553 */
554static int
555ieee80211_sta_join1(struct ieee80211_node *selbs)
556{
557 struct ieee80211com *ic = selbs->ni_ic;
558 struct ieee80211_node *obss;

--- 32 unchanged lines hidden (view full) ---

591
592 /*
593 * Delete unusable rates; we've already checked
594 * that the negotiated rate set is acceptable.
595 */
596 ieee80211_fix_rate(ic->ic_bss, &ic->ic_bss->ni_rates,
597 IEEE80211_F_DODEL | IEEE80211_F_JOIN);
598
587 ic->ic_bsschan = selbs->ni_chan;
588 ic->ic_curchan = ic->ic_bsschan;
589 ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
590 ic->ic_set_channel(ic);
599 ieee80211_setbsschan(ic, selbs->ni_chan);
591 /*
592 * Set the erp state (mostly the slot time) to deal with
593 * the auto-select case; this should be redundant if the
594 * mode is locked.
595 */
596 ieee80211_reset_erp(ic);
597 ieee80211_wme_initparams(ic);
598

--- 33 unchanged lines hidden (view full) ---

632 */
633 IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
634 ni->ni_esslen = se->se_ssid[1];
635 memcpy(ni->ni_essid, se->se_ssid+2, ni->ni_esslen);
636 ni->ni_rstamp = se->se_rstamp;
637 ni->ni_tstamp.tsf = se->se_tstamp.tsf;
638 ni->ni_intval = se->se_intval;
639 ni->ni_capinfo = se->se_capinfo;
600 /*
601 * Set the erp state (mostly the slot time) to deal with
602 * the auto-select case; this should be redundant if the
603 * mode is locked.
604 */
605 ieee80211_reset_erp(ic);
606 ieee80211_wme_initparams(ic);
607

--- 33 unchanged lines hidden (view full) ---

641 */
642 IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
643 ni->ni_esslen = se->se_ssid[1];
644 memcpy(ni->ni_essid, se->se_ssid+2, ni->ni_esslen);
645 ni->ni_rstamp = se->se_rstamp;
646 ni->ni_tstamp.tsf = se->se_tstamp.tsf;
647 ni->ni_intval = se->se_intval;
648 ni->ni_capinfo = se->se_capinfo;
640 /* XXX shift to 11n channel if htinfo present */
641 ni->ni_chan = se->se_chan;
642 ni->ni_timoff = se->se_timoff;
643 ni->ni_fhdwell = se->se_fhdwell;
644 ni->ni_fhindex = se->se_fhindex;
645 ni->ni_erp = se->se_erp;
646 ni->ni_rssi = se->se_rssi;
647 ni->ni_noise = se->se_noise;
648 if (se->se_htcap_ie != NULL)
649 ni->ni_chan = se->se_chan;
650 ni->ni_timoff = se->se_timoff;
651 ni->ni_fhdwell = se->se_fhdwell;
652 ni->ni_fhindex = se->se_fhindex;
653 ni->ni_erp = se->se_erp;
654 ni->ni_rssi = se->se_rssi;
655 ni->ni_noise = se->se_noise;
656 if (se->se_htcap_ie != NULL)
649 ieee80211_ht_node_init(ni, se->se_htcap_ie);
650 if (se->se_htinfo_ie != NULL)
651 ieee80211_parse_htinfo(ni, se->se_htinfo_ie);
657 ieee80211_saveie(&ni->ni_htcap_ie, se->se_htcap_ie);
652 if (se->se_wpa_ie != NULL)
653 ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);
654 if (se->se_rsn_ie != NULL)
655 ieee80211_saveie(&ni->ni_rsn_ie, se->se_rsn_ie);
656 if (se->se_wme_ie != NULL)
657 ieee80211_saveie(&ni->ni_wme_ie, se->se_wme_ie);
658 if (se->se_ath_ie != NULL)
659 ieee80211_saveath(ni, se->se_ath_ie);
660
661 ic->ic_dtim_period = se->se_dtimperiod;
662 ic->ic_dtim_count = 0;
663
664 /* NB: must be after ni_chan is setup */
665 ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
666 IEEE80211_F_DOSORT);
658 if (se->se_wpa_ie != NULL)
659 ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);
660 if (se->se_rsn_ie != NULL)
661 ieee80211_saveie(&ni->ni_rsn_ie, se->se_rsn_ie);
662 if (se->se_wme_ie != NULL)
663 ieee80211_saveie(&ni->ni_wme_ie, se->se_wme_ie);
664 if (se->se_ath_ie != NULL)
665 ieee80211_saveath(ni, se->se_ath_ie);
666
667 ic->ic_dtim_period = se->se_dtimperiod;
668 ic->ic_dtim_count = 0;
669
670 /* NB: must be after ni_chan is setup */
671 ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
672 IEEE80211_F_DOSORT);
667 if (se->se_htcap_ie != NULL)
668 ieee80211_setup_htrates(ni, se->se_htcap_ie, IEEE80211_F_JOIN);
669 if (se->se_htinfo_ie != NULL)
670 ieee80211_setup_basic_htrates(ni, se->se_htinfo_ie);
671
672 return ieee80211_sta_join1(ieee80211_ref_node(ni));
673}
674
675/*
676 * Leave the specified IBSS/BSS network. The node is assumed to
677 * be passed in with a held reference.
678 */

--- 32 unchanged lines hidden (view full) ---

711 if (ic->ic_opmode != IEEE80211_M_STA)
712 ic->ic_ps_sta--;
713 ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
714 IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
715 "[%s] power save mode off, %u sta's in ps mode\n",
716 ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
717 }
718 /*
673
674 return ieee80211_sta_join1(ieee80211_ref_node(ni));
675}
676
677/*
678 * Leave the specified IBSS/BSS network. The node is assumed to
679 * be passed in with a held reference.
680 */

--- 32 unchanged lines hidden (view full) ---

713 if (ic->ic_opmode != IEEE80211_M_STA)
714 ic->ic_ps_sta--;
715 ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
716 IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
717 "[%s] power save mode off, %u sta's in ps mode\n",
718 ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
719 }
720 /*
721 * Cleanup any HT-related state.
722 */
723 if (ni->ni_flags & IEEE80211_NODE_HT)
724 ieee80211_ht_node_cleanup(ni);
725 /*
719 * Clear AREF flag that marks the authorization refcnt bump
720 * has happened. This is probably not needed as the node
721 * should always be removed from the table so not found but
722 * do it just in case.
723 */
724 ni->ni_flags &= ~IEEE80211_NODE_AREF;
725
726 /*

--- 845 unchanged lines hidden (view full) ---

1572{
1573 struct ieee80211com *ic = arg;
1574
1575 ieee80211_scan_timeout(ic);
1576 ieee80211_timeout_stations(&ic->ic_sta);
1577
1578 IEEE80211_LOCK(ic);
1579 ieee80211_erp_timeout(ic);
726 * Clear AREF flag that marks the authorization refcnt bump
727 * has happened. This is probably not needed as the node
728 * should always be removed from the table so not found but
729 * do it just in case.
730 */
731 ni->ni_flags &= ~IEEE80211_NODE_AREF;
732
733 /*

--- 845 unchanged lines hidden (view full) ---

1579{
1580 struct ieee80211com *ic = arg;
1581
1582 ieee80211_scan_timeout(ic);
1583 ieee80211_timeout_stations(&ic->ic_sta);
1584
1585 IEEE80211_LOCK(ic);
1586 ieee80211_erp_timeout(ic);
1587 ieee80211_ht_timeout(ic);
1580 IEEE80211_UNLOCK(ic);
1581
1582 callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
1583 ieee80211_node_timeout, ic);
1584}
1585
1586void
1587ieee80211_iterate_nodes(struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg)

--- 66 unchanged lines hidden (view full) ---

1654
1655/*
1656 * Handle a station joining an 11g network.
1657 */
1658static void
1659ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
1660{
1661
1588 IEEE80211_UNLOCK(ic);
1589
1590 callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
1591 ieee80211_node_timeout, ic);
1592}
1593
1594void
1595ieee80211_iterate_nodes(struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg)

--- 66 unchanged lines hidden (view full) ---

1662
1663/*
1664 * Handle a station joining an 11g network.
1665 */
1666static void
1667ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
1668{
1669
1670 IEEE80211_LOCK_ASSERT(ic);
1671
1662 /*
1663 * Station isn't capable of short slot time. Bump
1664 * the count of long slot time stations and disable
1665 * use of short slot time. Note that the actual switch
1666 * over to long slot time use may not occur until the
1667 * next beacon transmission (per sec. 7.3.1.4 of 11g).
1668 */
1669 if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {

--- 49 unchanged lines hidden (view full) ---

1719void
1720ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp)
1721{
1722 int newassoc;
1723
1724 if (ni->ni_associd == 0) {
1725 uint16_t aid;
1726
1672 /*
1673 * Station isn't capable of short slot time. Bump
1674 * the count of long slot time stations and disable
1675 * use of short slot time. Note that the actual switch
1676 * over to long slot time use may not occur until the
1677 * next beacon transmission (per sec. 7.3.1.4 of 11g).
1678 */
1679 if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {

--- 49 unchanged lines hidden (view full) ---

1729void
1730ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp)
1731{
1732 int newassoc;
1733
1734 if (ni->ni_associd == 0) {
1735 uint16_t aid;
1736
1737 IEEE80211_LOCK(ic);
1727 /*
1728 * It would be good to search the bitmap
1729 * more efficiently, but this will do for now.
1730 */
1731 for (aid = 1; aid < ic->ic_max_aid; aid++) {
1732 if (!IEEE80211_AID_ISSET(aid,
1733 ic->ic_aid_bitmap))
1734 break;
1735 }
1736 if (aid >= ic->ic_max_aid) {
1738 /*
1739 * It would be good to search the bitmap
1740 * more efficiently, but this will do for now.
1741 */
1742 for (aid = 1; aid < ic->ic_max_aid; aid++) {
1743 if (!IEEE80211_AID_ISSET(aid,
1744 ic->ic_aid_bitmap))
1745 break;
1746 }
1747 if (aid >= ic->ic_max_aid) {
1748 IEEE80211_UNLOCK(ic);
1737 IEEE80211_SEND_MGMT(ic, ni, resp,
1738 IEEE80211_REASON_ASSOC_TOOMANY);
1739 ieee80211_node_leave(ic, ni);
1740 return;
1741 }
1742 ni->ni_associd = aid | 0xc000;
1749 IEEE80211_SEND_MGMT(ic, ni, resp,
1750 IEEE80211_REASON_ASSOC_TOOMANY);
1751 ieee80211_node_leave(ic, ni);
1752 return;
1753 }
1754 ni->ni_associd = aid | 0xc000;
1755 ni->ni_jointime = time_uptime;
1743 IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
1744 ic->ic_sta_assoc++;
1756 IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
1757 ic->ic_sta_assoc++;
1745 newassoc = 1;
1758
1759 if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
1760 ieee80211_ht_node_join(ni);
1746 if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
1747 IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
1748 ieee80211_node_join_11g(ic, ni);
1761 if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
1762 IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
1763 ieee80211_node_join_11g(ic, ni);
1764 IEEE80211_UNLOCK(ic);
1765
1766 newassoc = 1;
1749 } else
1750 newassoc = 0;
1751
1752 IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
1767 } else
1768 newassoc = 0;
1769
1770 IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
1753 "station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s",
1771 "station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
1754 newassoc ? "" : "re",
1755 IEEE80211_NODE_AID(ni),
1756 ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
1757 ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
1758 ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
1759 ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
1760 ni->ni_flags & IEEE80211_NODE_HT ?
1761 (ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
1772 newassoc ? "" : "re",
1773 IEEE80211_NODE_AID(ni),
1774 ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
1775 ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
1776 ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
1777 ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
1778 ni->ni_flags & IEEE80211_NODE_HT ?
1779 (ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
1780 ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
1762 IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
1763 ", fast-frames" : "",
1764 IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
1765 ", turbo" : ""
1766 );
1767
1768 /* give driver a chance to setup state like ni_txrate */
1769 if (ic->ic_newassoc != NULL)

--- 24 unchanged lines hidden (view full) ---

1794
1795/*
1796 * Handle a station leaving an 11g network.
1797 */
1798static void
1799ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
1800{
1801
1781 IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
1782 ", fast-frames" : "",
1783 IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
1784 ", turbo" : ""
1785 );
1786
1787 /* give driver a chance to setup state like ni_txrate */
1788 if (ic->ic_newassoc != NULL)

--- 24 unchanged lines hidden (view full) ---

1813
1814/*
1815 * Handle a station leaving an 11g network.
1816 */
1817static void
1818ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
1819{
1820
1821 IEEE80211_LOCK_ASSERT(ic);
1822
1802 KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
1803 ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,
1804 ic->ic_bsschan->ic_flags, ic->ic_curmode));
1805
1806 /*
1807 * If a long slot station do the slot time bookkeeping.
1808 */
1809 if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {

--- 85 unchanged lines hidden (view full) ---

1895 /*
1896 * Tell the authenticator the station is leaving.
1897 * Note that we must do this before yanking the
1898 * association id as the authenticator uses the
1899 * associd to locate it's state block.
1900 */
1901 if (ic->ic_auth->ia_node_leave != NULL)
1902 ic->ic_auth->ia_node_leave(ic, ni);
1823 KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
1824 ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,
1825 ic->ic_bsschan->ic_flags, ic->ic_curmode));
1826
1827 /*
1828 * If a long slot station do the slot time bookkeeping.
1829 */
1830 if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {

--- 85 unchanged lines hidden (view full) ---

1916 /*
1917 * Tell the authenticator the station is leaving.
1918 * Note that we must do this before yanking the
1919 * association id as the authenticator uses the
1920 * associd to locate it's state block.
1921 */
1922 if (ic->ic_auth->ia_node_leave != NULL)
1923 ic->ic_auth->ia_node_leave(ic, ni);
1924
1925 IEEE80211_LOCK(ic);
1903 IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
1904 ni->ni_associd = 0;
1905 ic->ic_sta_assoc--;
1906
1926 IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
1927 ni->ni_associd = 0;
1928 ic->ic_sta_assoc--;
1929
1930 if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
1931 ieee80211_ht_node_leave(ni);
1907 if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
1908 IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
1909 ieee80211_node_leave_11g(ic, ni);
1932 if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
1933 IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
1934 ieee80211_node_leave_11g(ic, ni);
1935 IEEE80211_UNLOCK(ic);
1910 /*
1911 * Cleanup station state. In particular clear various
1912 * state that might otherwise be reused if the node
1913 * is reused before the reference count goes to zero
1914 * (and memory is reclaimed).
1915 */
1916 ieee80211_sta_leave(ic, ni);
1917done:

--- 132 unchanged lines hidden ---
1936 /*
1937 * Cleanup station state. In particular clear various
1938 * state that might otherwise be reused if the node
1939 * is reused before the reference count goes to zero
1940 * (and memory is reclaimed).
1941 */
1942 ieee80211_sta_leave(ic, ni);
1943done:

--- 132 unchanged lines hidden ---