diff options
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 60 | ||||
-rw-r--r-- | drivers/net/bonding/bond_procfs.c | 43 | ||||
-rw-r--r-- | include/net/bond_3ad.h | 29 |
3 files changed, 125 insertions, 7 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cfc4a9c1000a..f61b2870cddf 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #define AD_STANDBY 0x2 | 38 | #define AD_STANDBY 0x2 |
39 | #define AD_MAX_TX_IN_SECOND 3 | 39 | #define AD_MAX_TX_IN_SECOND 3 |
40 | #define AD_COLLECTOR_MAX_DELAY 0 | 40 | #define AD_COLLECTOR_MAX_DELAY 0 |
41 | #define AD_MONITOR_CHURNED 0x1000 | ||
41 | 42 | ||
42 | /* Timer definitions (43.4.4 in the 802.3ad standard) */ | 43 | /* Timer definitions (43.4.4 in the 802.3ad standard) */ |
43 | #define AD_FAST_PERIODIC_TIME 1 | 44 | #define AD_FAST_PERIODIC_TIME 1 |
@@ -1013,16 +1014,19 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1013 | /* check if state machine should change state */ | 1014 | /* check if state machine should change state */ |
1014 | 1015 | ||
1015 | /* first, check if port was reinitialized */ | 1016 | /* first, check if port was reinitialized */ |
1016 | if (port->sm_vars & AD_PORT_BEGIN) | 1017 | if (port->sm_vars & AD_PORT_BEGIN) { |
1017 | port->sm_rx_state = AD_RX_INITIALIZE; | 1018 | port->sm_rx_state = AD_RX_INITIALIZE; |
1019 | port->sm_vars |= AD_MONITOR_CHURNED; | ||
1018 | /* check if port is not enabled */ | 1020 | /* check if port is not enabled */ |
1019 | else if (!(port->sm_vars & AD_PORT_BEGIN) | 1021 | } else if (!(port->sm_vars & AD_PORT_BEGIN) |
1020 | && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) | 1022 | && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) |
1021 | port->sm_rx_state = AD_RX_PORT_DISABLED; | 1023 | port->sm_rx_state = AD_RX_PORT_DISABLED; |
1022 | /* check if new lacpdu arrived */ | 1024 | /* check if new lacpdu arrived */ |
1023 | else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || | 1025 | else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || |
1024 | (port->sm_rx_state == AD_RX_DEFAULTED) || | 1026 | (port->sm_rx_state == AD_RX_DEFAULTED) || |
1025 | (port->sm_rx_state == AD_RX_CURRENT))) { | 1027 | (port->sm_rx_state == AD_RX_CURRENT))) { |
1028 | if (port->sm_rx_state != AD_RX_CURRENT) | ||
1029 | port->sm_vars |= AD_MONITOR_CHURNED; | ||
1026 | port->sm_rx_timer_counter = 0; | 1030 | port->sm_rx_timer_counter = 0; |
1027 | port->sm_rx_state = AD_RX_CURRENT; | 1031 | port->sm_rx_state = AD_RX_CURRENT; |
1028 | } else { | 1032 | } else { |
@@ -1100,9 +1104,11 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1100 | */ | 1104 | */ |
1101 | port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION; | 1105 | port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION; |
1102 | port->sm_vars &= ~AD_PORT_MATCHED; | 1106 | port->sm_vars &= ~AD_PORT_MATCHED; |
1107 | port->partner_oper.port_state |= AD_STATE_LACP_TIMEOUT; | ||
1103 | port->partner_oper.port_state |= AD_STATE_LACP_ACTIVITY; | 1108 | port->partner_oper.port_state |= AD_STATE_LACP_ACTIVITY; |
1104 | port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); | 1109 | port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); |
1105 | port->actor_oper_port_state |= AD_STATE_EXPIRED; | 1110 | port->actor_oper_port_state |= AD_STATE_EXPIRED; |
1111 | port->sm_vars |= AD_MONITOR_CHURNED; | ||
1106 | break; | 1112 | break; |
1107 | case AD_RX_DEFAULTED: | 1113 | case AD_RX_DEFAULTED: |
1108 | __update_default_selected(port); | 1114 | __update_default_selected(port); |
@@ -1132,6 +1138,45 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
1132 | } | 1138 | } |
1133 | 1139 | ||
1134 | /** | 1140 | /** |
1141 | * ad_churn_machine - handle port churn's state machine | ||
1142 | * @port: the port we're looking at | ||
1143 | * | ||
1144 | */ | ||
1145 | static void ad_churn_machine(struct port *port) | ||
1146 | { | ||
1147 | if (port->sm_vars & AD_MONITOR_CHURNED) { | ||
1148 | port->sm_vars &= ~AD_MONITOR_CHURNED; | ||
1149 | port->sm_churn_actor_state = AD_CHURN_MONITOR; | ||
1150 | port->sm_churn_partner_state = AD_CHURN_MONITOR; | ||
1151 | port->sm_churn_actor_timer_counter = | ||
1152 | __ad_timer_to_ticks(AD_ACTOR_CHURN_TIMER, 0); | ||
1153 | port->sm_churn_partner_timer_counter = | ||
1154 | __ad_timer_to_ticks(AD_PARTNER_CHURN_TIMER, 0); | ||
1155 | return; | ||
1156 | } | ||
1157 | if (port->sm_churn_actor_timer_counter && | ||
1158 | !(--port->sm_churn_actor_timer_counter) && | ||
1159 | port->sm_churn_actor_state == AD_CHURN_MONITOR) { | ||
1160 | if (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION) { | ||
1161 | port->sm_churn_actor_state = AD_NO_CHURN; | ||
1162 | } else { | ||
1163 | port->churn_actor_count++; | ||
1164 | port->sm_churn_actor_state = AD_CHURN; | ||
1165 | } | ||
1166 | } | ||
1167 | if (port->sm_churn_partner_timer_counter && | ||
1168 | !(--port->sm_churn_partner_timer_counter) && | ||
1169 | port->sm_churn_partner_state == AD_CHURN_MONITOR) { | ||
1170 | if (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) { | ||
1171 | port->sm_churn_partner_state = AD_NO_CHURN; | ||
1172 | } else { | ||
1173 | port->churn_partner_count++; | ||
1174 | port->sm_churn_partner_state = AD_CHURN; | ||
1175 | } | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | /** | ||
1135 | * ad_tx_machine - handle a port's tx state machine | 1180 | * ad_tx_machine - handle a port's tx state machine |
1136 | * @port: the port we're looking at | 1181 | * @port: the port we're looking at |
1137 | */ | 1182 | */ |
@@ -1745,6 +1790,13 @@ static void ad_initialize_port(struct port *port, int lacp_fast) | |||
1745 | port->next_port_in_aggregator = NULL; | 1790 | port->next_port_in_aggregator = NULL; |
1746 | port->transaction_id = 0; | 1791 | port->transaction_id = 0; |
1747 | 1792 | ||
1793 | port->sm_churn_actor_timer_counter = 0; | ||
1794 | port->sm_churn_actor_state = 0; | ||
1795 | port->churn_actor_count = 0; | ||
1796 | port->sm_churn_partner_timer_counter = 0; | ||
1797 | port->sm_churn_partner_state = 0; | ||
1798 | port->churn_partner_count = 0; | ||
1799 | |||
1748 | memcpy(&port->lacpdu, &lacpdu, sizeof(lacpdu)); | 1800 | memcpy(&port->lacpdu, &lacpdu, sizeof(lacpdu)); |
1749 | } | 1801 | } |
1750 | } | 1802 | } |
@@ -2164,6 +2216,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
2164 | ad_port_selection_logic(port, &update_slave_arr); | 2216 | ad_port_selection_logic(port, &update_slave_arr); |
2165 | ad_mux_machine(port, &update_slave_arr); | 2217 | ad_mux_machine(port, &update_slave_arr); |
2166 | ad_tx_machine(port); | 2218 | ad_tx_machine(port); |
2219 | ad_churn_machine(port); | ||
2167 | 2220 | ||
2168 | /* turn off the BEGIN bit, since we already handled it */ | 2221 | /* turn off the BEGIN bit, since we already handled it */ |
2169 | if (port->sm_vars & AD_PORT_BEGIN) | 2222 | if (port->sm_vars & AD_PORT_BEGIN) |
@@ -2485,6 +2538,9 @@ int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond, | |||
2485 | if (skb->protocol != PKT_TYPE_LACPDU) | 2538 | if (skb->protocol != PKT_TYPE_LACPDU) |
2486 | return RX_HANDLER_ANOTHER; | 2539 | return RX_HANDLER_ANOTHER; |
2487 | 2540 | ||
2541 | if (!MAC_ADDRESS_EQUAL(eth_hdr(skb)->h_dest, lacpdu_mcast_addr)) | ||
2542 | return RX_HANDLER_ANOTHER; | ||
2543 | |||
2488 | lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu); | 2544 | lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu); |
2489 | if (!lacpdu) | 2545 | if (!lacpdu) |
2490 | return RX_HANDLER_ANOTHER; | 2546 | return RX_HANDLER_ANOTHER; |
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c index 976f5ad2a0f2..62694cfc05b6 100644 --- a/drivers/net/bonding/bond_procfs.c +++ b/drivers/net/bonding/bond_procfs.c | |||
@@ -176,18 +176,51 @@ static void bond_info_show_slave(struct seq_file *seq, | |||
176 | slave->link_failure_count); | 176 | slave->link_failure_count); |
177 | 177 | ||
178 | seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr); | 178 | seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr); |
179 | seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id); | ||
179 | 180 | ||
180 | if (BOND_MODE(bond) == BOND_MODE_8023AD) { | 181 | if (BOND_MODE(bond) == BOND_MODE_8023AD) { |
181 | const struct aggregator *agg | 182 | const struct port *port = &SLAVE_AD_INFO(slave)->port; |
182 | = SLAVE_AD_INFO(slave)->port.aggregator; | 183 | const struct aggregator *agg = port->aggregator; |
183 | 184 | ||
184 | if (agg) | 185 | if (agg) { |
185 | seq_printf(seq, "Aggregator ID: %d\n", | 186 | seq_printf(seq, "Aggregator ID: %d\n", |
186 | agg->aggregator_identifier); | 187 | agg->aggregator_identifier); |
187 | else | 188 | seq_printf(seq, "Actor Churn State: %s\n", |
189 | bond_3ad_churn_desc(port->sm_churn_actor_state)); | ||
190 | seq_printf(seq, "Partner Churn State: %s\n", | ||
191 | bond_3ad_churn_desc(port->sm_churn_partner_state)); | ||
192 | seq_printf(seq, "Actor Churned Count: %d\n", | ||
193 | port->churn_actor_count); | ||
194 | seq_printf(seq, "Partner Churned Count: %d\n", | ||
195 | port->churn_partner_count); | ||
196 | |||
197 | seq_puts(seq, "details actor lacp pdu:\n"); | ||
198 | seq_printf(seq, " system priority: %d\n", | ||
199 | port->actor_system_priority); | ||
200 | seq_printf(seq, " port key: %d\n", | ||
201 | port->actor_oper_port_key); | ||
202 | seq_printf(seq, " port priority: %d\n", | ||
203 | port->actor_port_priority); | ||
204 | seq_printf(seq, " port number: %d\n", | ||
205 | port->actor_port_number); | ||
206 | seq_printf(seq, " port state: %d\n", | ||
207 | port->actor_oper_port_state); | ||
208 | |||
209 | seq_puts(seq, "details partner lacp pdu:\n"); | ||
210 | seq_printf(seq, " system priority: %d\n", | ||
211 | port->partner_oper.system_priority); | ||
212 | seq_printf(seq, " oper key: %d\n", | ||
213 | port->partner_oper.key); | ||
214 | seq_printf(seq, " port priority: %d\n", | ||
215 | port->partner_oper.port_priority); | ||
216 | seq_printf(seq, " port number: %d\n", | ||
217 | port->partner_oper.port_number); | ||
218 | seq_printf(seq, " port state: %d\n", | ||
219 | port->partner_oper.port_state); | ||
220 | } else { | ||
188 | seq_puts(seq, "Aggregator ID: N/A\n"); | 221 | seq_puts(seq, "Aggregator ID: N/A\n"); |
222 | } | ||
189 | } | 223 | } |
190 | seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id); | ||
191 | } | 224 | } |
192 | 225 | ||
193 | static int bond_info_seq_show(struct seq_file *seq, void *v) | 226 | static int bond_info_seq_show(struct seq_file *seq, void *v) |
diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h index f04cdbb7848e..c2a40a172fcd 100644 --- a/include/net/bond_3ad.h +++ b/include/net/bond_3ad.h | |||
@@ -82,6 +82,13 @@ typedef enum { | |||
82 | AD_TRANSMIT /* tx Machine */ | 82 | AD_TRANSMIT /* tx Machine */ |
83 | } tx_states_t; | 83 | } tx_states_t; |
84 | 84 | ||
85 | /* churn machine states(43.4.17 in the 802.3ad standard) */ | ||
86 | typedef enum { | ||
87 | AD_CHURN_MONITOR, /* monitoring for churn */ | ||
88 | AD_CHURN, /* churn detected (error) */ | ||
89 | AD_NO_CHURN /* no churn (no error) */ | ||
90 | } churn_state_t; | ||
91 | |||
85 | /* rx indication types */ | 92 | /* rx indication types */ |
86 | typedef enum { | 93 | typedef enum { |
87 | AD_TYPE_LACPDU = 1, /* type lacpdu */ | 94 | AD_TYPE_LACPDU = 1, /* type lacpdu */ |
@@ -229,6 +236,12 @@ typedef struct port { | |||
229 | u16 sm_mux_timer_counter; /* state machine mux timer counter */ | 236 | u16 sm_mux_timer_counter; /* state machine mux timer counter */ |
230 | tx_states_t sm_tx_state; /* state machine tx state */ | 237 | tx_states_t sm_tx_state; /* state machine tx state */ |
231 | u16 sm_tx_timer_counter; /* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */ | 238 | u16 sm_tx_timer_counter; /* state machine tx timer counter(allways on - enter to transmit state 3 time per second) */ |
239 | u16 sm_churn_actor_timer_counter; | ||
240 | u16 sm_churn_partner_timer_counter; | ||
241 | u32 churn_actor_count; | ||
242 | u32 churn_partner_count; | ||
243 | churn_state_t sm_churn_actor_state; | ||
244 | churn_state_t sm_churn_partner_state; | ||
232 | struct slave *slave; /* pointer to the bond slave that this port belongs to */ | 245 | struct slave *slave; /* pointer to the bond slave that this port belongs to */ |
233 | struct aggregator *aggregator; /* pointer to an aggregator that this port related to */ | 246 | struct aggregator *aggregator; /* pointer to an aggregator that this port related to */ |
234 | struct port *next_port_in_aggregator; /* Next port on the linked list of the parent aggregator */ | 247 | struct port *next_port_in_aggregator; /* Next port on the linked list of the parent aggregator */ |
@@ -262,6 +275,22 @@ struct ad_slave_info { | |||
262 | u16 id; | 275 | u16 id; |
263 | }; | 276 | }; |
264 | 277 | ||
278 | static inline const char *bond_3ad_churn_desc(churn_state_t state) | ||
279 | { | ||
280 | static const char *const churn_description[] = { | ||
281 | "monitoring", | ||
282 | "churned", | ||
283 | "none", | ||
284 | "unknown" | ||
285 | }; | ||
286 | int max_size = sizeof(churn_description) / sizeof(churn_description[0]); | ||
287 | |||
288 | if (state >= max_size) | ||
289 | state = max_size - 1; | ||
290 | |||
291 | return churn_description[state]; | ||
292 | } | ||
293 | |||
265 | /* ========== AD Exported functions to the main bonding code ========== */ | 294 | /* ========== AD Exported functions to the main bonding code ========== */ |
266 | void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution); | 295 | void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution); |
267 | void bond_3ad_bind_slave(struct slave *slave); | 296 | void bond_3ad_bind_slave(struct slave *slave); |