diff options
Diffstat (limited to 'drivers/net/bonding/bond_3ad.c')
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 326 |
1 files changed, 203 insertions, 123 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 6106660a4a44..ba1372f2f144 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | #include <linux/ethtool.h> | 29 | #include <linux/ethtool.h> |
30 | #include <linux/etherdevice.h> | ||
30 | #include <linux/if_bonding.h> | 31 | #include <linux/if_bonding.h> |
31 | #include <linux/pkt_sched.h> | 32 | #include <linux/pkt_sched.h> |
32 | #include <net/net_namespace.h> | 33 | #include <net/net_namespace.h> |
@@ -236,6 +237,17 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator) | |||
236 | return &(SLAVE_AD_INFO(slave->next).aggregator); | 237 | return &(SLAVE_AD_INFO(slave->next).aggregator); |
237 | } | 238 | } |
238 | 239 | ||
240 | /* | ||
241 | * __agg_has_partner | ||
242 | * | ||
243 | * Return nonzero if aggregator has a partner (denoted by a non-zero ether | ||
244 | * address for the partner). Return 0 if not. | ||
245 | */ | ||
246 | static inline int __agg_has_partner(struct aggregator *agg) | ||
247 | { | ||
248 | return !is_zero_ether_addr(agg->partner_system.mac_addr_value); | ||
249 | } | ||
250 | |||
239 | /** | 251 | /** |
240 | * __disable_port - disable the port's slave | 252 | * __disable_port - disable the port's slave |
241 | * @port: the port we're looking at | 253 | * @port: the port we're looking at |
@@ -274,14 +286,14 @@ static inline int __port_is_enabled(struct port *port) | |||
274 | * __get_agg_selection_mode - get the aggregator selection mode | 286 | * __get_agg_selection_mode - get the aggregator selection mode |
275 | * @port: the port we're looking at | 287 | * @port: the port we're looking at |
276 | * | 288 | * |
277 | * Get the aggregator selection mode. Can be %BANDWIDTH or %COUNT. | 289 | * Get the aggregator selection mode. Can be %STABLE, %BANDWIDTH or %COUNT. |
278 | */ | 290 | */ |
279 | static inline u32 __get_agg_selection_mode(struct port *port) | 291 | static inline u32 __get_agg_selection_mode(struct port *port) |
280 | { | 292 | { |
281 | struct bonding *bond = __get_bond_by_port(port); | 293 | struct bonding *bond = __get_bond_by_port(port); |
282 | 294 | ||
283 | if (bond == NULL) { | 295 | if (bond == NULL) { |
284 | return AD_BANDWIDTH; | 296 | return BOND_AD_STABLE; |
285 | } | 297 | } |
286 | 298 | ||
287 | return BOND_AD_INFO(bond).agg_select_mode; | 299 | return BOND_AD_INFO(bond).agg_select_mode; |
@@ -1414,9 +1426,82 @@ static void ad_port_selection_logic(struct port *port) | |||
1414 | // else set ready=FALSE in all aggregator's ports | 1426 | // else set ready=FALSE in all aggregator's ports |
1415 | __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); | 1427 | __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); |
1416 | 1428 | ||
1417 | if (!__check_agg_selection_timer(port) && (aggregator = __get_first_agg(port))) { | 1429 | aggregator = __get_first_agg(port); |
1418 | ad_agg_selection_logic(aggregator); | 1430 | ad_agg_selection_logic(aggregator); |
1431 | } | ||
1432 | |||
1433 | /* | ||
1434 | * Decide if "agg" is a better choice for the new active aggregator that | ||
1435 | * the current best, according to the ad_select policy. | ||
1436 | */ | ||
1437 | static struct aggregator *ad_agg_selection_test(struct aggregator *best, | ||
1438 | struct aggregator *curr) | ||
1439 | { | ||
1440 | /* | ||
1441 | * 0. If no best, select current. | ||
1442 | * | ||
1443 | * 1. If the current agg is not individual, and the best is | ||
1444 | * individual, select current. | ||
1445 | * | ||
1446 | * 2. If current agg is individual and the best is not, keep best. | ||
1447 | * | ||
1448 | * 3. Therefore, current and best are both individual or both not | ||
1449 | * individual, so: | ||
1450 | * | ||
1451 | * 3a. If current agg partner replied, and best agg partner did not, | ||
1452 | * select current. | ||
1453 | * | ||
1454 | * 3b. If current agg partner did not reply and best agg partner | ||
1455 | * did reply, keep best. | ||
1456 | * | ||
1457 | * 4. Therefore, current and best both have partner replies or | ||
1458 | * both do not, so perform selection policy: | ||
1459 | * | ||
1460 | * BOND_AD_COUNT: Select by count of ports. If count is equal, | ||
1461 | * select by bandwidth. | ||
1462 | * | ||
1463 | * BOND_AD_STABLE, BOND_AD_BANDWIDTH: Select by bandwidth. | ||
1464 | */ | ||
1465 | if (!best) | ||
1466 | return curr; | ||
1467 | |||
1468 | if (!curr->is_individual && best->is_individual) | ||
1469 | return curr; | ||
1470 | |||
1471 | if (curr->is_individual && !best->is_individual) | ||
1472 | return best; | ||
1473 | |||
1474 | if (__agg_has_partner(curr) && !__agg_has_partner(best)) | ||
1475 | return curr; | ||
1476 | |||
1477 | if (!__agg_has_partner(curr) && __agg_has_partner(best)) | ||
1478 | return best; | ||
1479 | |||
1480 | switch (__get_agg_selection_mode(curr->lag_ports)) { | ||
1481 | case BOND_AD_COUNT: | ||
1482 | if (curr->num_of_ports > best->num_of_ports) | ||
1483 | return curr; | ||
1484 | |||
1485 | if (curr->num_of_ports < best->num_of_ports) | ||
1486 | return best; | ||
1487 | |||
1488 | /*FALLTHROUGH*/ | ||
1489 | case BOND_AD_STABLE: | ||
1490 | case BOND_AD_BANDWIDTH: | ||
1491 | if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best)) | ||
1492 | return curr; | ||
1493 | |||
1494 | break; | ||
1495 | |||
1496 | default: | ||
1497 | printk(KERN_WARNING DRV_NAME | ||
1498 | ": %s: Impossible agg select mode %d\n", | ||
1499 | curr->slave->dev->master->name, | ||
1500 | __get_agg_selection_mode(curr->lag_ports)); | ||
1501 | break; | ||
1419 | } | 1502 | } |
1503 | |||
1504 | return best; | ||
1420 | } | 1505 | } |
1421 | 1506 | ||
1422 | /** | 1507 | /** |
@@ -1424,156 +1509,138 @@ static void ad_port_selection_logic(struct port *port) | |||
1424 | * @aggregator: the aggregator we're looking at | 1509 | * @aggregator: the aggregator we're looking at |
1425 | * | 1510 | * |
1426 | * It is assumed that only one aggregator may be selected for a team. | 1511 | * It is assumed that only one aggregator may be selected for a team. |
1427 | * The logic of this function is to select (at first time) the aggregator with | 1512 | * |
1428 | * the most ports attached to it, and to reselect the active aggregator only if | 1513 | * The logic of this function is to select the aggregator according to |
1429 | * the previous aggregator has no more ports related to it. | 1514 | * the ad_select policy: |
1515 | * | ||
1516 | * BOND_AD_STABLE: select the aggregator with the most ports attached to | ||
1517 | * it, and to reselect the active aggregator only if the previous | ||
1518 | * aggregator has no more ports related to it. | ||
1519 | * | ||
1520 | * BOND_AD_BANDWIDTH: select the aggregator with the highest total | ||
1521 | * bandwidth, and reselect whenever a link state change takes place or the | ||
1522 | * set of slaves in the bond changes. | ||
1523 | * | ||
1524 | * BOND_AD_COUNT: select the aggregator with largest number of ports | ||
1525 | * (slaves), and reselect whenever a link state change takes place or the | ||
1526 | * set of slaves in the bond changes. | ||
1430 | * | 1527 | * |
1431 | * FIXME: this function MUST be called with the first agg in the bond, or | 1528 | * FIXME: this function MUST be called with the first agg in the bond, or |
1432 | * __get_active_agg() won't work correctly. This function should be better | 1529 | * __get_active_agg() won't work correctly. This function should be better |
1433 | * called with the bond itself, and retrieve the first agg from it. | 1530 | * called with the bond itself, and retrieve the first agg from it. |
1434 | */ | 1531 | */ |
1435 | static void ad_agg_selection_logic(struct aggregator *aggregator) | 1532 | static void ad_agg_selection_logic(struct aggregator *agg) |
1436 | { | 1533 | { |
1437 | struct aggregator *best_aggregator = NULL, *active_aggregator = NULL; | 1534 | struct aggregator *best, *active, *origin; |
1438 | struct aggregator *last_active_aggregator = NULL, *origin_aggregator; | ||
1439 | struct port *port; | 1535 | struct port *port; |
1440 | u16 num_of_aggs=0; | ||
1441 | 1536 | ||
1442 | origin_aggregator = aggregator; | 1537 | origin = agg; |
1443 | 1538 | ||
1444 | //get current active aggregator | 1539 | active = __get_active_agg(agg); |
1445 | last_active_aggregator = __get_active_agg(aggregator); | 1540 | best = active; |
1446 | 1541 | ||
1447 | // search for the aggregator with the most ports attached to it. | ||
1448 | do { | 1542 | do { |
1449 | // count how many candidate lag's we have | 1543 | agg->is_active = 0; |
1450 | if (aggregator->lag_ports) { | 1544 | |
1451 | num_of_aggs++; | 1545 | if (agg->num_of_ports) |
1452 | } | 1546 | best = ad_agg_selection_test(best, agg); |
1453 | if (aggregator->is_active && !aggregator->is_individual && // if current aggregator is the active aggregator | 1547 | |
1454 | MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr))) { // and partner answers to 802.3ad PDUs | 1548 | } while ((agg = __get_next_agg(agg))); |
1455 | if (aggregator->num_of_ports) { // if any ports attached to the current aggregator | 1549 | |
1456 | best_aggregator=NULL; // disregard the best aggregator that was chosen by now | 1550 | if (best && |
1457 | break; // stop the selection of other aggregator if there are any ports attached to this active aggregator | 1551 | __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) { |
1458 | } else { // no ports attached to this active aggregator | 1552 | /* |
1459 | aggregator->is_active = 0; // mark this aggregator as not active anymore | 1553 | * For the STABLE policy, don't replace the old active |
1554 | * aggregator if it's still active (it has an answering | ||
1555 | * partner) or if both the best and active don't have an | ||
1556 | * answering partner. | ||
1557 | */ | ||
1558 | if (active && active->lag_ports && | ||
1559 | active->lag_ports->is_enabled && | ||
1560 | (__agg_has_partner(active) || | ||
1561 | (!__agg_has_partner(active) && !__agg_has_partner(best)))) { | ||
1562 | if (!(!active->actor_oper_aggregator_key && | ||
1563 | best->actor_oper_aggregator_key)) { | ||
1564 | best = NULL; | ||
1565 | active->is_active = 1; | ||
1460 | } | 1566 | } |
1461 | } | 1567 | } |
1462 | if (aggregator->num_of_ports) { // if any ports attached | 1568 | } |
1463 | if (best_aggregator) { // if there is a candidte aggregator | ||
1464 | //The reasons for choosing new best aggregator: | ||
1465 | // 1. if current agg is NOT individual and the best agg chosen so far is individual OR | ||
1466 | // current and best aggs are both individual or both not individual, AND | ||
1467 | // 2a. current agg partner reply but best agg partner do not reply OR | ||
1468 | // 2b. current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply AND | ||
1469 | // current has more ports/bandwidth, or same amount of ports but current has faster ports, THEN | ||
1470 | // current agg become best agg so far | ||
1471 | |||
1472 | //if current agg is NOT individual and the best agg chosen so far is individual change best_aggregator | ||
1473 | if (!aggregator->is_individual && best_aggregator->is_individual) { | ||
1474 | best_aggregator=aggregator; | ||
1475 | } | ||
1476 | // current and best aggs are both individual or both not individual | ||
1477 | else if ((aggregator->is_individual && best_aggregator->is_individual) || | ||
1478 | (!aggregator->is_individual && !best_aggregator->is_individual)) { | ||
1479 | // current and best aggs are both individual or both not individual AND | ||
1480 | // current agg partner reply but best agg partner do not reply | ||
1481 | if ((MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) && | ||
1482 | !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) { | ||
1483 | best_aggregator=aggregator; | ||
1484 | } | ||
1485 | // current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply | ||
1486 | else if (! (!MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) && | ||
1487 | MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) { | ||
1488 | if ((__get_agg_selection_mode(aggregator->lag_ports) == AD_BANDWIDTH)&& | ||
1489 | (__get_agg_bandwidth(aggregator) > __get_agg_bandwidth(best_aggregator))) { | ||
1490 | best_aggregator=aggregator; | ||
1491 | } else if (__get_agg_selection_mode(aggregator->lag_ports) == AD_COUNT) { | ||
1492 | if (((aggregator->num_of_ports > best_aggregator->num_of_ports) && | ||
1493 | (aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS))|| | ||
1494 | ((aggregator->num_of_ports == best_aggregator->num_of_ports) && | ||
1495 | ((u16)(aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS) > | ||
1496 | (u16)(best_aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS)))) { | ||
1497 | best_aggregator=aggregator; | ||
1498 | } | ||
1499 | } | ||
1500 | } | ||
1501 | } | ||
1502 | } else { | ||
1503 | best_aggregator=aggregator; | ||
1504 | } | ||
1505 | } | ||
1506 | aggregator->is_active = 0; // mark all aggregators as not active anymore | ||
1507 | } while ((aggregator = __get_next_agg(aggregator))); | ||
1508 | |||
1509 | // if we have new aggregator selected, don't replace the old aggregator if it has an answering partner, | ||
1510 | // or if both old aggregator and new aggregator don't have answering partner | ||
1511 | if (best_aggregator) { | ||
1512 | if (last_active_aggregator && last_active_aggregator->lag_ports && last_active_aggregator->lag_ports->is_enabled && | ||
1513 | (MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) || // partner answers OR | ||
1514 | (!MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) && // both old and new | ||
1515 | !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) // partner do not answer | ||
1516 | ) { | ||
1517 | // if new aggregator has link, and old aggregator does not, replace old aggregator.(do nothing) | ||
1518 | // -> don't replace otherwise. | ||
1519 | if (!(!last_active_aggregator->actor_oper_aggregator_key && best_aggregator->actor_oper_aggregator_key)) { | ||
1520 | best_aggregator=NULL; | ||
1521 | last_active_aggregator->is_active = 1; // don't replace good old aggregator | ||
1522 | 1569 | ||
1523 | } | 1570 | if (best && (best == active)) { |
1524 | } | 1571 | best = NULL; |
1572 | active->is_active = 1; | ||
1525 | } | 1573 | } |
1526 | 1574 | ||
1527 | // if there is new best aggregator, activate it | 1575 | // if there is new best aggregator, activate it |
1528 | if (best_aggregator) { | 1576 | if (best) { |
1529 | for (aggregator = __get_first_agg(best_aggregator->lag_ports); | 1577 | dprintk("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", |
1530 | aggregator; | 1578 | best->aggregator_identifier, best->num_of_ports, |
1531 | aggregator = __get_next_agg(aggregator)) { | 1579 | best->actor_oper_aggregator_key, |
1532 | 1580 | best->partner_oper_aggregator_key, | |
1533 | dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n", | 1581 | best->is_individual, best->is_active); |
1534 | aggregator->aggregator_identifier, aggregator->num_of_ports, | 1582 | dprintk("best ports %p slave %p %s\n", |
1535 | aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key, | 1583 | best->lag_ports, best->slave, |
1536 | aggregator->is_individual, aggregator->is_active); | 1584 | best->slave ? best->slave->dev->name : "NULL"); |
1585 | |||
1586 | for (agg = __get_first_agg(best->lag_ports); agg; | ||
1587 | agg = __get_next_agg(agg)) { | ||
1588 | |||
1589 | dprintk("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", | ||
1590 | agg->aggregator_identifier, agg->num_of_ports, | ||
1591 | agg->actor_oper_aggregator_key, | ||
1592 | agg->partner_oper_aggregator_key, | ||
1593 | agg->is_individual, agg->is_active); | ||
1537 | } | 1594 | } |
1538 | 1595 | ||
1539 | // check if any partner replys | 1596 | // check if any partner replys |
1540 | if (best_aggregator->is_individual) { | 1597 | if (best->is_individual) { |
1541 | printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from " | 1598 | printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad" |
1542 | "the link partner for any adapters in the bond\n", | 1599 | " response from the link partner for any" |
1543 | best_aggregator->slave->dev->master->name); | 1600 | " adapters in the bond\n", |
1544 | } | 1601 | best->slave->dev->master->name); |
1545 | |||
1546 | // check if there are more than one aggregator | ||
1547 | if (num_of_aggs > 1) { | ||
1548 | dprintk("Warning: More than one Link Aggregation Group was " | ||
1549 | "found in the bond. Only one group will function in the bond\n"); | ||
1550 | } | 1602 | } |
1551 | 1603 | ||
1552 | best_aggregator->is_active = 1; | 1604 | best->is_active = 1; |
1553 | dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier); | 1605 | dprintk("LAG %d chosen as the active LAG\n", |
1554 | dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n", | 1606 | best->aggregator_identifier); |
1555 | best_aggregator->aggregator_identifier, best_aggregator->num_of_ports, | 1607 | dprintk("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", |
1556 | best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key, | 1608 | best->aggregator_identifier, best->num_of_ports, |
1557 | best_aggregator->is_individual, best_aggregator->is_active); | 1609 | best->actor_oper_aggregator_key, |
1610 | best->partner_oper_aggregator_key, | ||
1611 | best->is_individual, best->is_active); | ||
1558 | 1612 | ||
1559 | // disable the ports that were related to the former active_aggregator | 1613 | // disable the ports that were related to the former active_aggregator |
1560 | if (last_active_aggregator) { | 1614 | if (active) { |
1561 | for (port=last_active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) { | 1615 | for (port = active->lag_ports; port; |
1616 | port = port->next_port_in_aggregator) { | ||
1562 | __disable_port(port); | 1617 | __disable_port(port); |
1563 | } | 1618 | } |
1564 | } | 1619 | } |
1565 | } | 1620 | } |
1566 | 1621 | ||
1567 | // if the selected aggregator is of join individuals(partner_system is NULL), enable their ports | 1622 | /* |
1568 | active_aggregator = __get_active_agg(origin_aggregator); | 1623 | * if the selected aggregator is of join individuals |
1624 | * (partner_system is NULL), enable their ports | ||
1625 | */ | ||
1626 | active = __get_active_agg(origin); | ||
1569 | 1627 | ||
1570 | if (active_aggregator) { | 1628 | if (active) { |
1571 | if (!MAC_ADDRESS_COMPARE(&(active_aggregator->partner_system), &(null_mac_addr))) { | 1629 | if (!__agg_has_partner(active)) { |
1572 | for (port=active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) { | 1630 | for (port = active->lag_ports; port; |
1631 | port = port->next_port_in_aggregator) { | ||
1573 | __enable_port(port); | 1632 | __enable_port(port); |
1574 | } | 1633 | } |
1575 | } | 1634 | } |
1576 | } | 1635 | } |
1636 | |||
1637 | if (origin->slave) { | ||
1638 | struct bonding *bond; | ||
1639 | |||
1640 | bond = bond_get_bond_by_slave(origin->slave); | ||
1641 | if (bond) | ||
1642 | bond_3ad_set_carrier(bond); | ||
1643 | } | ||
1577 | } | 1644 | } |
1578 | 1645 | ||
1579 | /** | 1646 | /** |
@@ -1830,6 +1897,19 @@ static void ad_initialize_lacpdu(struct lacpdu *lacpdu) | |||
1830 | // Check aggregators status in team every T seconds | 1897 | // Check aggregators status in team every T seconds |
1831 | #define AD_AGGREGATOR_SELECTION_TIMER 8 | 1898 | #define AD_AGGREGATOR_SELECTION_TIMER 8 |
1832 | 1899 | ||
1900 | /* | ||
1901 | * bond_3ad_initiate_agg_selection(struct bonding *bond) | ||
1902 | * | ||
1903 | * Set the aggregation selection timer, to initiate an agg selection in | ||
1904 | * the very near future. Called during first initialization, and during | ||
1905 | * any down to up transitions of the bond. | ||
1906 | */ | ||
1907 | void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout) | ||
1908 | { | ||
1909 | BOND_AD_INFO(bond).agg_select_timer = timeout; | ||
1910 | BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select; | ||
1911 | } | ||
1912 | |||
1833 | static u16 aggregator_identifier; | 1913 | static u16 aggregator_identifier; |
1834 | 1914 | ||
1835 | /** | 1915 | /** |
@@ -1854,9 +1934,9 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas | |||
1854 | // initialize how many times this module is called in one second(should be about every 100ms) | 1934 | // initialize how many times this module is called in one second(should be about every 100ms) |
1855 | ad_ticks_per_sec = tick_resolution; | 1935 | ad_ticks_per_sec = tick_resolution; |
1856 | 1936 | ||
1857 | // initialize the aggregator selection timer(to activate an aggregation selection after initialize) | 1937 | bond_3ad_initiate_agg_selection(bond, |
1858 | BOND_AD_INFO(bond).agg_select_timer = (AD_AGGREGATOR_SELECTION_TIMER * ad_ticks_per_sec); | 1938 | AD_AGGREGATOR_SELECTION_TIMER * |
1859 | BOND_AD_INFO(bond).agg_select_mode = AD_BANDWIDTH; | 1939 | ad_ticks_per_sec); |
1860 | } | 1940 | } |
1861 | } | 1941 | } |
1862 | 1942 | ||