Commit 3fdddd85 authored by dingtianhong's avatar dingtianhong Committed by David S. Miller

bonding: alloc the structure ad_info dynamically in per slave

The struct ad_slave_info is very huge, and only be used for 802.3ad mode,
so alloc the structure dynamically could save 356 Bits for every slave in
non 802.3ad mode.

Cc: Jay Vosburgh <j.vosburgh@gmail.com>
Cc: Veaceslav Falico <vfalico@gmail.com>
Cc: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: default avatarDing Tianhong <dingtianhong@huawei.com>
Acked-by: default avatarVeaceslav Falico <vfalico@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 86b5d251
...@@ -157,7 +157,7 @@ static inline struct aggregator *__get_first_agg(struct port *port) ...@@ -157,7 +157,7 @@ static inline struct aggregator *__get_first_agg(struct port *port)
rcu_read_lock(); rcu_read_lock();
first_slave = bond_first_slave_rcu(bond); first_slave = bond_first_slave_rcu(bond);
agg = first_slave ? &(SLAVE_AD_INFO(first_slave).aggregator) : NULL; agg = first_slave ? &(SLAVE_AD_INFO(first_slave)->aggregator) : NULL;
rcu_read_unlock(); rcu_read_unlock();
return agg; return agg;
...@@ -241,7 +241,7 @@ static inline int __check_agg_selection_timer(struct port *port) ...@@ -241,7 +241,7 @@ static inline int __check_agg_selection_timer(struct port *port)
*/ */
static inline void __get_state_machine_lock(struct port *port) static inline void __get_state_machine_lock(struct port *port)
{ {
spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); spin_lock_bh(&(SLAVE_AD_INFO(port->slave)->state_machine_lock));
} }
/** /**
...@@ -250,7 +250,7 @@ static inline void __get_state_machine_lock(struct port *port) ...@@ -250,7 +250,7 @@ static inline void __get_state_machine_lock(struct port *port)
*/ */
static inline void __release_state_machine_lock(struct port *port) static inline void __release_state_machine_lock(struct port *port)
{ {
spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); spin_unlock_bh(&(SLAVE_AD_INFO(port->slave)->state_machine_lock));
} }
/** /**
...@@ -350,7 +350,7 @@ static u8 __get_duplex(struct port *port) ...@@ -350,7 +350,7 @@ static u8 __get_duplex(struct port *port)
static inline void __initialize_port_locks(struct slave *slave) static inline void __initialize_port_locks(struct slave *slave)
{ {
/* make sure it isn't called twice */ /* make sure it isn't called twice */
spin_lock_init(&(SLAVE_AD_INFO(slave).state_machine_lock)); spin_lock_init(&(SLAVE_AD_INFO(slave)->state_machine_lock));
} }
/* Conversions */ /* Conversions */
...@@ -688,8 +688,8 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator) ...@@ -688,8 +688,8 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator)
struct slave *slave; struct slave *slave;
bond_for_each_slave_rcu(bond, slave, iter) bond_for_each_slave_rcu(bond, slave, iter)
if (SLAVE_AD_INFO(slave).aggregator.is_active) if (SLAVE_AD_INFO(slave)->aggregator.is_active)
return &(SLAVE_AD_INFO(slave).aggregator); return &(SLAVE_AD_INFO(slave)->aggregator);
return NULL; return NULL;
} }
...@@ -1293,7 +1293,7 @@ static void ad_port_selection_logic(struct port *port) ...@@ -1293,7 +1293,7 @@ static void ad_port_selection_logic(struct port *port)
} }
/* search on all aggregators for a suitable aggregator for this port */ /* search on all aggregators for a suitable aggregator for this port */
bond_for_each_slave(bond, slave, iter) { bond_for_each_slave(bond, slave, iter) {
aggregator = &(SLAVE_AD_INFO(slave).aggregator); aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
/* keep a free aggregator for later use(if needed) */ /* keep a free aggregator for later use(if needed) */
if (!aggregator->lag_ports) { if (!aggregator->lag_ports) {
...@@ -1504,7 +1504,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) ...@@ -1504,7 +1504,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
best = (active && agg_device_up(active)) ? active : NULL; best = (active && agg_device_up(active)) ? active : NULL;
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
agg = &(SLAVE_AD_INFO(slave).aggregator); agg = &(SLAVE_AD_INFO(slave)->aggregator);
agg->is_active = 0; agg->is_active = 0;
...@@ -1549,7 +1549,7 @@ static void ad_agg_selection_logic(struct aggregator *agg) ...@@ -1549,7 +1549,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
best->slave ? best->slave->dev->name : "NULL"); best->slave ? best->slave->dev->name : "NULL");
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
agg = &(SLAVE_AD_INFO(slave).aggregator); agg = &(SLAVE_AD_INFO(slave)->aggregator);
pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
agg->aggregator_identifier, agg->num_of_ports, agg->aggregator_identifier, agg->num_of_ports,
...@@ -1840,16 +1840,16 @@ void bond_3ad_bind_slave(struct slave *slave) ...@@ -1840,16 +1840,16 @@ void bond_3ad_bind_slave(struct slave *slave)
struct aggregator *aggregator; struct aggregator *aggregator;
/* check that the slave has not been initialized yet. */ /* check that the slave has not been initialized yet. */
if (SLAVE_AD_INFO(slave).port.slave != slave) { if (SLAVE_AD_INFO(slave)->port.slave != slave) {
/* port initialization */ /* port initialization */
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
ad_initialize_port(port, bond->params.lacp_fast); ad_initialize_port(port, bond->params.lacp_fast);
__initialize_port_locks(slave); __initialize_port_locks(slave);
port->slave = slave; port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave).id; port->actor_port_number = SLAVE_AD_INFO(slave)->id;
/* key is determined according to the link speed, duplex and user key(which /* key is determined according to the link speed, duplex and user key(which
* is yet not supported) * is yet not supported)
*/ */
...@@ -1874,7 +1874,7 @@ void bond_3ad_bind_slave(struct slave *slave) ...@@ -1874,7 +1874,7 @@ void bond_3ad_bind_slave(struct slave *slave)
__disable_port(port); __disable_port(port);
/* aggregator initialization */ /* aggregator initialization */
aggregator = &(SLAVE_AD_INFO(slave).aggregator); aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
ad_initialize_agg(aggregator); ad_initialize_agg(aggregator);
...@@ -1903,8 +1903,8 @@ void bond_3ad_unbind_slave(struct slave *slave) ...@@ -1903,8 +1903,8 @@ void bond_3ad_unbind_slave(struct slave *slave)
struct slave *slave_iter; struct slave *slave_iter;
struct list_head *iter; struct list_head *iter;
aggregator = &(SLAVE_AD_INFO(slave).aggregator); aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
/* if slave is null, the whole port is not initialized */ /* if slave is null, the whole port is not initialized */
if (!port->slave) { if (!port->slave) {
...@@ -1932,7 +1932,7 @@ void bond_3ad_unbind_slave(struct slave *slave) ...@@ -1932,7 +1932,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
(aggregator->lag_ports->next_port_in_aggregator)) { (aggregator->lag_ports->next_port_in_aggregator)) {
/* find new aggregator for the related port(s) */ /* find new aggregator for the related port(s) */
bond_for_each_slave(bond, slave_iter, iter) { bond_for_each_slave(bond, slave_iter, iter) {
new_aggregator = &(SLAVE_AD_INFO(slave_iter).aggregator); new_aggregator = &(SLAVE_AD_INFO(slave_iter)->aggregator);
/* if the new aggregator is empty, or it is /* if the new aggregator is empty, or it is
* connected to our port only * connected to our port only
*/ */
...@@ -2010,7 +2010,7 @@ void bond_3ad_unbind_slave(struct slave *slave) ...@@ -2010,7 +2010,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
/* find the aggregator that this port is connected to */ /* find the aggregator that this port is connected to */
bond_for_each_slave(bond, slave_iter, iter) { bond_for_each_slave(bond, slave_iter, iter) {
temp_aggregator = &(SLAVE_AD_INFO(slave_iter).aggregator); temp_aggregator = &(SLAVE_AD_INFO(slave_iter)->aggregator);
prev_port = NULL; prev_port = NULL;
/* search the port in the aggregator's related ports */ /* search the port in the aggregator's related ports */
for (temp_port = temp_aggregator->lag_ports; temp_port; for (temp_port = temp_aggregator->lag_ports; temp_port;
...@@ -2076,7 +2076,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) ...@@ -2076,7 +2076,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
if (BOND_AD_INFO(bond).agg_select_timer && if (BOND_AD_INFO(bond).agg_select_timer &&
!(--BOND_AD_INFO(bond).agg_select_timer)) { !(--BOND_AD_INFO(bond).agg_select_timer)) {
slave = bond_first_slave_rcu(bond); slave = bond_first_slave_rcu(bond);
port = slave ? &(SLAVE_AD_INFO(slave).port) : NULL; port = slave ? &(SLAVE_AD_INFO(slave)->port) : NULL;
/* select the active aggregator for the bond */ /* select the active aggregator for the bond */
if (port) { if (port) {
...@@ -2094,7 +2094,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) ...@@ -2094,7 +2094,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
/* for each port run the state machines */ /* for each port run the state machines */
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
if (!port->slave) { if (!port->slave) {
pr_warn_ratelimited("%s: Warning: Found an uninitialized port\n", pr_warn_ratelimited("%s: Warning: Found an uninitialized port\n",
bond->dev->name); bond->dev->name);
...@@ -2155,7 +2155,7 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, ...@@ -2155,7 +2155,7 @@ static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
if (length >= sizeof(struct lacpdu)) { if (length >= sizeof(struct lacpdu)) {
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
if (!port->slave) { if (!port->slave) {
pr_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", pr_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
...@@ -2212,7 +2212,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) ...@@ -2212,7 +2212,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
{ {
struct port *port; struct port *port;
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
/* if slave is null, the whole port is not initialized */ /* if slave is null, the whole port is not initialized */
if (!port->slave) { if (!port->slave) {
...@@ -2245,7 +2245,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) ...@@ -2245,7 +2245,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
{ {
struct port *port; struct port *port;
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
/* if slave is null, the whole port is not initialized */ /* if slave is null, the whole port is not initialized */
if (!port->slave) { if (!port->slave) {
...@@ -2279,7 +2279,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) ...@@ -2279,7 +2279,7 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
{ {
struct port *port; struct port *port;
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
/* if slave is null, the whole port is not initialized */ /* if slave is null, the whole port is not initialized */
if (!port->slave) { if (!port->slave) {
...@@ -2347,7 +2347,7 @@ int bond_3ad_set_carrier(struct bonding *bond) ...@@ -2347,7 +2347,7 @@ int bond_3ad_set_carrier(struct bonding *bond)
ret = 0; ret = 0;
goto out; goto out;
} }
active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator)); active = __get_active_agg(&(SLAVE_AD_INFO(first_slave)->aggregator));
if (active) { if (active) {
/* are enough slaves available to consider link up? */ /* are enough slaves available to consider link up? */
if (active->num_of_ports < bond->params.min_links) { if (active->num_of_ports < bond->params.min_links) {
...@@ -2384,7 +2384,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond, ...@@ -2384,7 +2384,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
struct port *port; struct port *port;
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
if (port->aggregator && port->aggregator->is_active) { if (port->aggregator && port->aggregator->is_active) {
aggregator = port->aggregator; aggregator = port->aggregator;
break; break;
...@@ -2444,7 +2444,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) ...@@ -2444,7 +2444,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
first_ok_slave = NULL; first_ok_slave = NULL;
bond_for_each_slave_rcu(bond, slave, iter) { bond_for_each_slave_rcu(bond, slave, iter) {
agg = SLAVE_AD_INFO(slave).port.aggregator; agg = SLAVE_AD_INFO(slave)->port.aggregator;
if (!agg || agg->aggregator_identifier != agg_id) if (!agg || agg->aggregator_identifier != agg_id)
continue; continue;
...@@ -2522,7 +2522,7 @@ void bond_3ad_update_lacp_rate(struct bonding *bond) ...@@ -2522,7 +2522,7 @@ void bond_3ad_update_lacp_rate(struct bonding *bond)
lacp_fast = bond->params.lacp_fast; lacp_fast = bond->params.lacp_fast;
bond_for_each_slave(bond, slave, iter) { bond_for_each_slave(bond, slave, iter) {
port = &(SLAVE_AD_INFO(slave).port); port = &(SLAVE_AD_INFO(slave)->port);
__get_state_machine_lock(port); __get_state_machine_lock(port);
if (lacp_fast) if (lacp_fast)
port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
......
...@@ -1163,6 +1163,35 @@ static void bond_upper_dev_unlink(struct net_device *bond_dev, ...@@ -1163,6 +1163,35 @@ static void bond_upper_dev_unlink(struct net_device *bond_dev,
rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL); rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL);
} }
static struct slave *bond_alloc_slave(struct bonding *bond)
{
struct slave *slave = NULL;
slave = kzalloc(sizeof(struct slave), GFP_KERNEL);
if (!slave)
return NULL;
if (bond->params.mode == BOND_MODE_8023AD) {
SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info),
GFP_KERNEL);
if (!SLAVE_AD_INFO(slave)) {
kfree(slave);
return NULL;
}
}
return slave;
}
static void bond_free_slave(struct slave *slave)
{
struct bonding *bond = bond_get_bond_by_slave(slave);
if (bond->params.mode == BOND_MODE_8023AD)
kfree(SLAVE_AD_INFO(slave));
kfree(slave);
}
/* enslave device <slave> to bond device <master> */ /* enslave device <slave> to bond device <master> */
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{ {
...@@ -1290,11 +1319,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1290,11 +1319,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond->dev->addr_assign_type == NET_ADDR_RANDOM) bond->dev->addr_assign_type == NET_ADDR_RANDOM)
bond_set_dev_addr(bond->dev, slave_dev); bond_set_dev_addr(bond->dev, slave_dev);
new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); new_slave = bond_alloc_slave(bond);
if (!new_slave) { if (!new_slave) {
res = -ENOMEM; res = -ENOMEM;
goto err_undo_flags; goto err_undo_flags;
} }
/* /*
* Set the new_slave's queue_id to be zero. Queue ID mapping * Set the new_slave's queue_id to be zero. Queue ID mapping
* is set via sysfs or module option if desired. * is set via sysfs or module option if desired.
...@@ -1471,14 +1501,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1471,14 +1501,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW); bond_set_slave_inactive_flags(new_slave, BOND_SLAVE_NOTIFY_NOW);
/* if this is the first slave */ /* if this is the first slave */
if (!prev_slave) { if (!prev_slave) {
SLAVE_AD_INFO(new_slave).id = 1; SLAVE_AD_INFO(new_slave)->id = 1;
/* Initialize AD with the number of times that the AD timer is called in 1 second /* Initialize AD with the number of times that the AD timer is called in 1 second
* can be called only after the mac address of the bond is set * can be called only after the mac address of the bond is set
*/ */
bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL); bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
} else { } else {
SLAVE_AD_INFO(new_slave).id = SLAVE_AD_INFO(new_slave)->id =
SLAVE_AD_INFO(prev_slave).id + 1; SLAVE_AD_INFO(prev_slave)->id + 1;
} }
bond_3ad_bind_slave(new_slave); bond_3ad_bind_slave(new_slave);
...@@ -1599,7 +1629,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1599,7 +1629,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
dev_set_mtu(slave_dev, new_slave->original_mtu); dev_set_mtu(slave_dev, new_slave->original_mtu);
err_free: err_free:
kfree(new_slave); bond_free_slave(new_slave);
err_undo_flags: err_undo_flags:
/* Enslave of first slave has failed and we need to fix master's mac */ /* Enslave of first slave has failed and we need to fix master's mac */
...@@ -1786,7 +1816,7 @@ static int __bond_release_one(struct net_device *bond_dev, ...@@ -1786,7 +1816,7 @@ static int __bond_release_one(struct net_device *bond_dev,
slave_dev->priv_flags &= ~IFF_BONDING; slave_dev->priv_flags &= ~IFF_BONDING;
kfree(slave); bond_free_slave(slave);
return 0; /* deletion OK */ return 0; /* deletion OK */
} }
......
...@@ -59,7 +59,7 @@ static int bond_fill_slave_info(struct sk_buff *skb, ...@@ -59,7 +59,7 @@ static int bond_fill_slave_info(struct sk_buff *skb,
if (slave->bond->params.mode == BOND_MODE_8023AD) { if (slave->bond->params.mode == BOND_MODE_8023AD) {
const struct aggregator *agg; const struct aggregator *agg;
agg = SLAVE_AD_INFO(slave).port.aggregator; agg = SLAVE_AD_INFO(slave)->port.aggregator;
if (agg) if (agg)
if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, if (nla_put_u16(skb, IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
agg->aggregator_identifier)) agg->aggregator_identifier))
......
...@@ -190,7 +190,7 @@ static void bond_info_show_slave(struct seq_file *seq, ...@@ -190,7 +190,7 @@ static void bond_info_show_slave(struct seq_file *seq,
if (bond->params.mode == BOND_MODE_8023AD) { if (bond->params.mode == BOND_MODE_8023AD) {
const struct aggregator *agg const struct aggregator *agg
= SLAVE_AD_INFO(slave).port.aggregator; = SLAVE_AD_INFO(slave)->port.aggregator;
if (agg) if (agg)
seq_printf(seq, "Aggregator ID: %d\n", seq_printf(seq, "Aggregator ID: %d\n",
......
...@@ -70,7 +70,7 @@ static ssize_t ad_aggregator_id_show(struct slave *slave, char *buf) ...@@ -70,7 +70,7 @@ static ssize_t ad_aggregator_id_show(struct slave *slave, char *buf)
const struct aggregator *agg; const struct aggregator *agg;
if (slave->bond->params.mode == BOND_MODE_8023AD) { if (slave->bond->params.mode == BOND_MODE_8023AD) {
agg = SLAVE_AD_INFO(slave).port.aggregator; agg = SLAVE_AD_INFO(slave)->port.aggregator;
if (agg) if (agg)
return sprintf(buf, "%d\n", return sprintf(buf, "%d\n",
agg->aggregator_identifier); agg->aggregator_identifier);
......
...@@ -203,7 +203,7 @@ struct slave { ...@@ -203,7 +203,7 @@ struct slave {
u32 speed; u32 speed;
u16 queue_id; u16 queue_id;
u8 perm_hwaddr[ETH_ALEN]; u8 perm_hwaddr[ETH_ALEN];
struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */ struct ad_slave_info *ad_info;
struct tlb_slave_info tlb_info; struct tlb_slave_info tlb_info;
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *np; struct netpoll *np;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment