diff options
Diffstat (limited to 'drivers/net/bonding/bond_3ad.c')
| -rw-r--r-- | drivers/net/bonding/bond_3ad.c | 359 |
1 files changed, 173 insertions, 186 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 0ddf4c66afe2..c7537abca4f2 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
| @@ -93,7 +93,7 @@ | |||
| 93 | // compare MAC addresses | 93 | // compare MAC addresses |
| 94 | #define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN) | 94 | #define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN) |
| 95 | 95 | ||
| 96 | static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}}; | 96 | static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } }; |
| 97 | static u16 ad_ticks_per_sec; | 97 | static u16 ad_ticks_per_sec; |
| 98 | static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000; | 98 | static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000; |
| 99 | 99 | ||
| @@ -129,9 +129,8 @@ static void ad_marker_response_received(struct bond_marker *marker, struct port | |||
| 129 | */ | 129 | */ |
| 130 | static inline struct bonding *__get_bond_by_port(struct port *port) | 130 | static inline struct bonding *__get_bond_by_port(struct port *port) |
| 131 | { | 131 | { |
| 132 | if (port->slave == NULL) { | 132 | if (port->slave == NULL) |
| 133 | return NULL; | 133 | return NULL; |
| 134 | } | ||
| 135 | 134 | ||
| 136 | return bond_get_bond_by_slave(port->slave); | 135 | return bond_get_bond_by_slave(port->slave); |
| 137 | } | 136 | } |
| @@ -144,9 +143,8 @@ static inline struct bonding *__get_bond_by_port(struct port *port) | |||
| 144 | */ | 143 | */ |
| 145 | static inline struct port *__get_first_port(struct bonding *bond) | 144 | static inline struct port *__get_first_port(struct bonding *bond) |
| 146 | { | 145 | { |
| 147 | if (bond->slave_cnt == 0) { | 146 | if (bond->slave_cnt == 0) |
| 148 | return NULL; | 147 | return NULL; |
| 149 | } | ||
| 150 | 148 | ||
| 151 | return &(SLAVE_AD_INFO(bond->first_slave).port); | 149 | return &(SLAVE_AD_INFO(bond->first_slave).port); |
| 152 | } | 150 | } |
| @@ -164,9 +162,8 @@ static inline struct port *__get_next_port(struct port *port) | |||
| 164 | struct slave *slave = port->slave; | 162 | struct slave *slave = port->slave; |
| 165 | 163 | ||
| 166 | // If there's no bond for this port, or this is the last slave | 164 | // If there's no bond for this port, or this is the last slave |
| 167 | if ((bond == NULL) || (slave->next == bond->first_slave)) { | 165 | if ((bond == NULL) || (slave->next == bond->first_slave)) |
| 168 | return NULL; | 166 | return NULL; |
| 169 | } | ||
| 170 | 167 | ||
| 171 | return &(SLAVE_AD_INFO(slave->next).port); | 168 | return &(SLAVE_AD_INFO(slave->next).port); |
| 172 | } | 169 | } |
| @@ -183,9 +180,8 @@ static inline struct aggregator *__get_first_agg(struct port *port) | |||
| 183 | struct bonding *bond = __get_bond_by_port(port); | 180 | struct bonding *bond = __get_bond_by_port(port); |
| 184 | 181 | ||
| 185 | // If there's no bond for this port, or bond has no slaves | 182 | // If there's no bond for this port, or bond has no slaves |
| 186 | if ((bond == NULL) || (bond->slave_cnt == 0)) { | 183 | if ((bond == NULL) || (bond->slave_cnt == 0)) |
| 187 | return NULL; | 184 | return NULL; |
| 188 | } | ||
| 189 | 185 | ||
| 190 | return &(SLAVE_AD_INFO(bond->first_slave).aggregator); | 186 | return &(SLAVE_AD_INFO(bond->first_slave).aggregator); |
| 191 | } | 187 | } |
| @@ -203,9 +199,8 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator) | |||
| 203 | struct bonding *bond = bond_get_bond_by_slave(slave); | 199 | struct bonding *bond = bond_get_bond_by_slave(slave); |
| 204 | 200 | ||
| 205 | // If there's no bond for this aggregator, or this is the last slave | 201 | // If there's no bond for this aggregator, or this is the last slave |
| 206 | if ((bond == NULL) || (slave->next == bond->first_slave)) { | 202 | if ((bond == NULL) || (slave->next == bond->first_slave)) |
| 207 | return NULL; | 203 | return NULL; |
| 208 | } | ||
| 209 | 204 | ||
| 210 | return &(SLAVE_AD_INFO(slave->next).aggregator); | 205 | return &(SLAVE_AD_INFO(slave->next).aggregator); |
| 211 | } | 206 | } |
| @@ -240,9 +235,8 @@ static inline void __enable_port(struct port *port) | |||
| 240 | { | 235 | { |
| 241 | struct slave *slave = port->slave; | 236 | struct slave *slave = port->slave; |
| 242 | 237 | ||
| 243 | if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) { | 238 | if ((slave->link == BOND_LINK_UP) && IS_UP(slave->dev)) |
| 244 | bond_set_slave_active_flags(slave); | 239 | bond_set_slave_active_flags(slave); |
| 245 | } | ||
| 246 | } | 240 | } |
| 247 | 241 | ||
| 248 | /** | 242 | /** |
| @@ -252,7 +246,7 @@ static inline void __enable_port(struct port *port) | |||
| 252 | */ | 246 | */ |
| 253 | static inline int __port_is_enabled(struct port *port) | 247 | static inline int __port_is_enabled(struct port *port) |
| 254 | { | 248 | { |
| 255 | return(port->slave->state == BOND_STATE_ACTIVE); | 249 | return bond_is_active_slave(port->slave); |
| 256 | } | 250 | } |
| 257 | 251 | ||
| 258 | /** | 252 | /** |
| @@ -265,9 +259,8 @@ static inline u32 __get_agg_selection_mode(struct port *port) | |||
| 265 | { | 259 | { |
| 266 | struct bonding *bond = __get_bond_by_port(port); | 260 | struct bonding *bond = __get_bond_by_port(port); |
| 267 | 261 | ||
| 268 | if (bond == NULL) { | 262 | if (bond == NULL) |
| 269 | return BOND_AD_STABLE; | 263 | return BOND_AD_STABLE; |
| 270 | } | ||
| 271 | 264 | ||
| 272 | return BOND_AD_INFO(bond).agg_select_mode; | 265 | return BOND_AD_INFO(bond).agg_select_mode; |
| 273 | } | 266 | } |
| @@ -281,31 +274,30 @@ static inline int __check_agg_selection_timer(struct port *port) | |||
| 281 | { | 274 | { |
| 282 | struct bonding *bond = __get_bond_by_port(port); | 275 | struct bonding *bond = __get_bond_by_port(port); |
| 283 | 276 | ||
| 284 | if (bond == NULL) { | 277 | if (bond == NULL) |
| 285 | return 0; | 278 | return 0; |
| 286 | } | ||
| 287 | 279 | ||
| 288 | return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0; | 280 | return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0; |
| 289 | } | 281 | } |
| 290 | 282 | ||
| 291 | /** | 283 | /** |
| 292 | * __get_rx_machine_lock - lock the port's RX machine | 284 | * __get_state_machine_lock - lock the port's state machines |
| 293 | * @port: the port we're looking at | 285 | * @port: the port we're looking at |
| 294 | * | 286 | * |
| 295 | */ | 287 | */ |
| 296 | static inline void __get_rx_machine_lock(struct port *port) | 288 | static inline void __get_state_machine_lock(struct port *port) |
| 297 | { | 289 | { |
| 298 | spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 290 | spin_lock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
| 299 | } | 291 | } |
| 300 | 292 | ||
| 301 | /** | 293 | /** |
| 302 | * __release_rx_machine_lock - unlock the port's RX machine | 294 | * __release_state_machine_lock - unlock the port's state machines |
| 303 | * @port: the port we're looking at | 295 | * @port: the port we're looking at |
| 304 | * | 296 | * |
| 305 | */ | 297 | */ |
| 306 | static inline void __release_rx_machine_lock(struct port *port) | 298 | static inline void __release_state_machine_lock(struct port *port) |
| 307 | { | 299 | { |
| 308 | spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 300 | spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
| 309 | } | 301 | } |
| 310 | 302 | ||
| 311 | /** | 303 | /** |
| @@ -328,9 +320,9 @@ static u16 __get_link_speed(struct port *port) | |||
| 328 | * link down, it sets the speed to 0. | 320 | * link down, it sets the speed to 0. |
| 329 | * This is done in spite of the fact that the e100 driver reports 0 to be | 321 | * This is done in spite of the fact that the e100 driver reports 0 to be |
| 330 | * compatible with MVT in the future.*/ | 322 | * compatible with MVT in the future.*/ |
| 331 | if (slave->link != BOND_LINK_UP) { | 323 | if (slave->link != BOND_LINK_UP) |
| 332 | speed=0; | 324 | speed = 0; |
| 333 | } else { | 325 | else { |
| 334 | switch (slave->speed) { | 326 | switch (slave->speed) { |
| 335 | case SPEED_10: | 327 | case SPEED_10: |
| 336 | speed = AD_LINK_SPEED_BITMASK_10MBPS; | 328 | speed = AD_LINK_SPEED_BITMASK_10MBPS; |
| @@ -375,18 +367,18 @@ static u8 __get_duplex(struct port *port) | |||
| 375 | 367 | ||
| 376 | // handling a special case: when the configuration starts with | 368 | // handling a special case: when the configuration starts with |
| 377 | // link down, it sets the duplex to 0. | 369 | // link down, it sets the duplex to 0. |
| 378 | if (slave->link != BOND_LINK_UP) { | 370 | if (slave->link != BOND_LINK_UP) |
| 379 | retval=0x0; | 371 | retval = 0x0; |
| 380 | } else { | 372 | else { |
| 381 | switch (slave->duplex) { | 373 | switch (slave->duplex) { |
| 382 | case DUPLEX_FULL: | 374 | case DUPLEX_FULL: |
| 383 | retval=0x1; | 375 | retval = 0x1; |
| 384 | pr_debug("Port %d Received status full duplex update from adapter\n", | 376 | pr_debug("Port %d Received status full duplex update from adapter\n", |
| 385 | port->actor_port_number); | 377 | port->actor_port_number); |
| 386 | break; | 378 | break; |
| 387 | case DUPLEX_HALF: | 379 | case DUPLEX_HALF: |
| 388 | default: | 380 | default: |
| 389 | retval=0x0; | 381 | retval = 0x0; |
| 390 | pr_debug("Port %d Received status NOT full duplex update from adapter\n", | 382 | pr_debug("Port %d Received status NOT full duplex update from adapter\n", |
| 391 | port->actor_port_number); | 383 | port->actor_port_number); |
| 392 | break; | 384 | break; |
| @@ -396,14 +388,14 @@ static u8 __get_duplex(struct port *port) | |||
| 396 | } | 388 | } |
| 397 | 389 | ||
| 398 | /** | 390 | /** |
| 399 | * __initialize_port_locks - initialize a port's RX machine spinlock | 391 | * __initialize_port_locks - initialize a port's STATE machine spinlock |
| 400 | * @port: the port we're looking at | 392 | * @port: the port we're looking at |
| 401 | * | 393 | * |
| 402 | */ | 394 | */ |
| 403 | static inline void __initialize_port_locks(struct port *port) | 395 | static inline void __initialize_port_locks(struct port *port) |
| 404 | { | 396 | { |
| 405 | // make sure it isn't called twice | 397 | // make sure it isn't called twice |
| 406 | spin_lock_init(&(SLAVE_AD_INFO(port->slave).rx_machine_lock)); | 398 | spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock)); |
| 407 | } | 399 | } |
| 408 | 400 | ||
| 409 | //conversions | 401 | //conversions |
| @@ -419,15 +411,14 @@ static inline void __initialize_port_locks(struct port *port) | |||
| 419 | */ | 411 | */ |
| 420 | static u16 __ad_timer_to_ticks(u16 timer_type, u16 par) | 412 | static u16 __ad_timer_to_ticks(u16 timer_type, u16 par) |
| 421 | { | 413 | { |
| 422 | u16 retval=0; //to silence the compiler | 414 | u16 retval = 0; /* to silence the compiler */ |
| 423 | 415 | ||
| 424 | switch (timer_type) { | 416 | switch (timer_type) { |
| 425 | case AD_CURRENT_WHILE_TIMER: // for rx machine usage | 417 | case AD_CURRENT_WHILE_TIMER: // for rx machine usage |
| 426 | if (par) { // for short or long timeout | 418 | if (par) |
| 427 | retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout | 419 | retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout |
| 428 | } else { | 420 | else |
| 429 | retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout | 421 | retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout |
| 430 | } | ||
| 431 | break; | 422 | break; |
| 432 | case AD_ACTOR_CHURN_TIMER: // for local churn machine | 423 | case AD_ACTOR_CHURN_TIMER: // for local churn machine |
| 433 | retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec); | 424 | retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec); |
| @@ -519,11 +510,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port) | |||
| 519 | port->actor_oper_port_state &= ~AD_STATE_DEFAULTED; | 510 | port->actor_oper_port_state &= ~AD_STATE_DEFAULTED; |
| 520 | 511 | ||
| 521 | // set the partner sync. to on if the partner is sync. and the port is matched | 512 | // set the partner sync. to on if the partner is sync. and the port is matched |
| 522 | if ((port->sm_vars & AD_PORT_MATCHED) && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) { | 513 | if ((port->sm_vars & AD_PORT_MATCHED) |
| 514 | && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) | ||
| 523 | partner->port_state |= AD_STATE_SYNCHRONIZATION; | 515 | partner->port_state |= AD_STATE_SYNCHRONIZATION; |
| 524 | } else { | 516 | else |
| 525 | partner->port_state &= ~AD_STATE_SYNCHRONIZATION; | 517 | partner->port_state &= ~AD_STATE_SYNCHRONIZATION; |
| 526 | } | ||
| 527 | } | 518 | } |
| 528 | } | 519 | } |
| 529 | 520 | ||
| @@ -653,7 +644,7 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port) | |||
| 653 | */ | 644 | */ |
| 654 | static void __attach_bond_to_agg(struct port *port) | 645 | static void __attach_bond_to_agg(struct port *port) |
| 655 | { | 646 | { |
| 656 | port=NULL; // just to satisfy the compiler | 647 | port = NULL; /* just to satisfy the compiler */ |
| 657 | // This function does nothing since the parser/multiplexer of the receive | 648 | // This function does nothing since the parser/multiplexer of the receive |
| 658 | // and the parser/multiplexer of the aggregator are already combined | 649 | // and the parser/multiplexer of the aggregator are already combined |
| 659 | } | 650 | } |
| @@ -668,7 +659,7 @@ static void __attach_bond_to_agg(struct port *port) | |||
| 668 | */ | 659 | */ |
| 669 | static void __detach_bond_from_agg(struct port *port) | 660 | static void __detach_bond_from_agg(struct port *port) |
| 670 | { | 661 | { |
| 671 | port=NULL; // just to satisfy the compiler | 662 | port = NULL; /* just to satisfy the compiler */ |
| 672 | // This function does nothing sience the parser/multiplexer of the receive | 663 | // This function does nothing sience the parser/multiplexer of the receive |
| 673 | // and the parser/multiplexer of the aggregator are already combined | 664 | // and the parser/multiplexer of the aggregator are already combined |
| 674 | } | 665 | } |
| @@ -685,7 +676,9 @@ static int __agg_ports_are_ready(struct aggregator *aggregator) | |||
| 685 | 676 | ||
| 686 | if (aggregator) { | 677 | if (aggregator) { |
| 687 | // scan all ports in this aggregator to verfy if they are all ready | 678 | // scan all ports in this aggregator to verfy if they are all ready |
| 688 | for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) { | 679 | for (port = aggregator->lag_ports; |
| 680 | port; | ||
| 681 | port = port->next_port_in_aggregator) { | ||
| 689 | if (!(port->sm_vars & AD_PORT_READY_N)) { | 682 | if (!(port->sm_vars & AD_PORT_READY_N)) { |
| 690 | retval = 0; | 683 | retval = 0; |
| 691 | break; | 684 | break; |
| @@ -706,12 +699,12 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val) | |||
| 706 | { | 699 | { |
| 707 | struct port *port; | 700 | struct port *port; |
| 708 | 701 | ||
| 709 | for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) { | 702 | for (port = aggregator->lag_ports; port; |
| 710 | if (val) { | 703 | port = port->next_port_in_aggregator) { |
| 704 | if (val) | ||
| 711 | port->sm_vars |= AD_PORT_READY; | 705 | port->sm_vars |= AD_PORT_READY; |
| 712 | } else { | 706 | else |
| 713 | port->sm_vars &= ~AD_PORT_READY; | 707 | port->sm_vars &= ~AD_PORT_READY; |
| 714 | } | ||
| 715 | } | 708 | } |
| 716 | } | 709 | } |
| 717 | 710 | ||
| @@ -722,12 +715,10 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val) | |||
| 722 | */ | 715 | */ |
| 723 | static u32 __get_agg_bandwidth(struct aggregator *aggregator) | 716 | static u32 __get_agg_bandwidth(struct aggregator *aggregator) |
| 724 | { | 717 | { |
| 725 | u32 bandwidth=0; | 718 | u32 bandwidth = 0; |
| 726 | u32 basic_speed; | ||
| 727 | 719 | ||
| 728 | if (aggregator->num_of_ports) { | 720 | if (aggregator->num_of_ports) { |
| 729 | basic_speed = __get_link_speed(aggregator->lag_ports); | 721 | switch (__get_link_speed(aggregator->lag_ports)) { |
| 730 | switch (basic_speed) { | ||
| 731 | case AD_LINK_SPEED_BITMASK_1MBPS: | 722 | case AD_LINK_SPEED_BITMASK_1MBPS: |
| 732 | bandwidth = aggregator->num_of_ports; | 723 | bandwidth = aggregator->num_of_ports; |
| 733 | break; | 724 | break; |
| @@ -744,7 +735,7 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) | |||
| 744 | bandwidth = aggregator->num_of_ports * 10000; | 735 | bandwidth = aggregator->num_of_ports * 10000; |
| 745 | break; | 736 | break; |
| 746 | default: | 737 | default: |
| 747 | bandwidth=0; // to silent the compilor .... | 738 | bandwidth = 0; /*to silence the compiler ....*/ |
| 748 | } | 739 | } |
| 749 | } | 740 | } |
| 750 | return bandwidth; | 741 | return bandwidth; |
| @@ -835,9 +826,8 @@ static int ad_lacpdu_send(struct port *port) | |||
| 835 | int length = sizeof(struct lacpdu_header); | 826 | int length = sizeof(struct lacpdu_header); |
| 836 | 827 | ||
| 837 | skb = dev_alloc_skb(length); | 828 | skb = dev_alloc_skb(length); |
| 838 | if (!skb) { | 829 | if (!skb) |
| 839 | return -ENOMEM; | 830 | return -ENOMEM; |
| 840 | } | ||
| 841 | 831 | ||
| 842 | skb->dev = slave->dev; | 832 | skb->dev = slave->dev; |
| 843 | skb_reset_mac_header(skb); | 833 | skb_reset_mac_header(skb); |
| @@ -848,7 +838,7 @@ static int ad_lacpdu_send(struct port *port) | |||
| 848 | lacpdu_header = (struct lacpdu_header *)skb_put(skb, length); | 838 | lacpdu_header = (struct lacpdu_header *)skb_put(skb, length); |
| 849 | 839 | ||
| 850 | memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); | 840 | memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); |
| 851 | /* Note: source addres is set to be the member's PERMANENT address, | 841 | /* Note: source address is set to be the member's PERMANENT address, |
| 852 | because we use it to identify loopback lacpdus in receive. */ | 842 | because we use it to identify loopback lacpdus in receive. */ |
| 853 | memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); | 843 | memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); |
| 854 | lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU; | 844 | lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU; |
| @@ -876,9 +866,8 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker) | |||
| 876 | int length = sizeof(struct bond_marker_header); | 866 | int length = sizeof(struct bond_marker_header); |
| 877 | 867 | ||
| 878 | skb = dev_alloc_skb(length + 16); | 868 | skb = dev_alloc_skb(length + 16); |
| 879 | if (!skb) { | 869 | if (!skb) |
| 880 | return -ENOMEM; | 870 | return -ENOMEM; |
| 881 | } | ||
| 882 | 871 | ||
| 883 | skb_reserve(skb, 16); | 872 | skb_reserve(skb, 16); |
| 884 | 873 | ||
| @@ -890,7 +879,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker) | |||
| 890 | marker_header = (struct bond_marker_header *)skb_put(skb, length); | 879 | marker_header = (struct bond_marker_header *)skb_put(skb, length); |
| 891 | 880 | ||
| 892 | memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); | 881 | memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN); |
| 893 | /* Note: source addres is set to be the member's PERMANENT address, | 882 | /* Note: source address is set to be the member's PERMANENT address, |
| 894 | because we use it to identify loopback MARKERs in receive. */ | 883 | because we use it to identify loopback MARKERs in receive. */ |
| 895 | memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); | 884 | memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN); |
| 896 | marker_header->hdr.h_proto = PKT_TYPE_LACPDU; | 885 | marker_header->hdr.h_proto = PKT_TYPE_LACPDU; |
| @@ -919,9 +908,10 @@ static void ad_mux_machine(struct port *port) | |||
| 919 | } else { | 908 | } else { |
| 920 | switch (port->sm_mux_state) { | 909 | switch (port->sm_mux_state) { |
| 921 | case AD_MUX_DETACHED: | 910 | case AD_MUX_DETACHED: |
| 922 | if ((port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if SELECTED or STANDBY | 911 | if ((port->sm_vars & AD_PORT_SELECTED) |
| 912 | || (port->sm_vars & AD_PORT_STANDBY)) | ||
| 913 | /* if SELECTED or STANDBY */ | ||
| 923 | port->sm_mux_state = AD_MUX_WAITING; // next state | 914 | port->sm_mux_state = AD_MUX_WAITING; // next state |
| 924 | } | ||
| 925 | break; | 915 | break; |
| 926 | case AD_MUX_WAITING: | 916 | case AD_MUX_WAITING: |
| 927 | // if SELECTED == FALSE return to DETACH state | 917 | // if SELECTED == FALSE return to DETACH state |
| @@ -935,18 +925,18 @@ static void ad_mux_machine(struct port *port) | |||
| 935 | } | 925 | } |
| 936 | 926 | ||
| 937 | // check if the wait_while_timer expired | 927 | // check if the wait_while_timer expired |
| 938 | if (port->sm_mux_timer_counter && !(--port->sm_mux_timer_counter)) { | 928 | if (port->sm_mux_timer_counter |
| 929 | && !(--port->sm_mux_timer_counter)) | ||
| 939 | port->sm_vars |= AD_PORT_READY_N; | 930 | port->sm_vars |= AD_PORT_READY_N; |
| 940 | } | ||
| 941 | 931 | ||
| 942 | // in order to withhold the selection logic to check all ports READY_N value | 932 | // in order to withhold the selection logic to check all ports READY_N value |
| 943 | // every callback cycle to update ready variable, we check READY_N and update READY here | 933 | // every callback cycle to update ready variable, we check READY_N and update READY here |
| 944 | __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); | 934 | __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); |
| 945 | 935 | ||
| 946 | // if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state | 936 | // if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state |
| 947 | if ((port->sm_vars & AD_PORT_READY) && !port->sm_mux_timer_counter) { | 937 | if ((port->sm_vars & AD_PORT_READY) |
| 938 | && !port->sm_mux_timer_counter) | ||
| 948 | port->sm_mux_state = AD_MUX_ATTACHED; // next state | 939 | port->sm_mux_state = AD_MUX_ATTACHED; // next state |
| 949 | } | ||
| 950 | break; | 940 | break; |
| 951 | case AD_MUX_ATTACHED: | 941 | case AD_MUX_ATTACHED: |
| 952 | // check also if agg_select_timer expired(so the edable port will take place only after this timer) | 942 | // check also if agg_select_timer expired(so the edable port will take place only after this timer) |
| @@ -1033,21 +1023,19 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
| 1033 | { | 1023 | { |
| 1034 | rx_states_t last_state; | 1024 | rx_states_t last_state; |
| 1035 | 1025 | ||
| 1036 | // Lock to prevent 2 instances of this function to run simultaneously(rx interrupt and periodic machine callback) | ||
| 1037 | __get_rx_machine_lock(port); | ||
| 1038 | |||
| 1039 | // keep current State Machine state to compare later if it was changed | 1026 | // keep current State Machine state to compare later if it was changed |
| 1040 | last_state = port->sm_rx_state; | 1027 | last_state = port->sm_rx_state; |
| 1041 | 1028 | ||
| 1042 | // check if state machine should change state | 1029 | // check if state machine should change state |
| 1043 | // first, check if port was reinitialized | 1030 | // first, check if port was reinitialized |
| 1044 | if (port->sm_vars & AD_PORT_BEGIN) { | 1031 | if (port->sm_vars & AD_PORT_BEGIN) |
| 1045 | port->sm_rx_state = AD_RX_INITIALIZE; // next state | 1032 | /* next state */ |
| 1046 | } | 1033 | port->sm_rx_state = AD_RX_INITIALIZE; |
| 1047 | // check if port is not enabled | 1034 | // check if port is not enabled |
| 1048 | else if (!(port->sm_vars & AD_PORT_BEGIN) && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) { | 1035 | else if (!(port->sm_vars & AD_PORT_BEGIN) |
| 1049 | port->sm_rx_state = AD_RX_PORT_DISABLED; // next state | 1036 | && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED)) |
| 1050 | } | 1037 | /* next state */ |
| 1038 | port->sm_rx_state = AD_RX_PORT_DISABLED; | ||
| 1051 | // check if new lacpdu arrived | 1039 | // check if new lacpdu arrived |
| 1052 | else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) { | 1040 | else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) { |
| 1053 | port->sm_rx_timer_counter = 0; // zero timer | 1041 | port->sm_rx_timer_counter = 0; // zero timer |
| @@ -1069,13 +1057,16 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
| 1069 | // if no lacpdu arrived and no timer is on | 1057 | // if no lacpdu arrived and no timer is on |
| 1070 | switch (port->sm_rx_state) { | 1058 | switch (port->sm_rx_state) { |
| 1071 | case AD_RX_PORT_DISABLED: | 1059 | case AD_RX_PORT_DISABLED: |
| 1072 | if (port->sm_vars & AD_PORT_MOVED) { | 1060 | if (port->sm_vars & AD_PORT_MOVED) |
| 1073 | port->sm_rx_state = AD_RX_INITIALIZE; // next state | 1061 | port->sm_rx_state = AD_RX_INITIALIZE; // next state |
| 1074 | } else if (port->is_enabled && (port->sm_vars & AD_PORT_LACP_ENABLED)) { | 1062 | else if (port->is_enabled |
| 1063 | && (port->sm_vars | ||
| 1064 | & AD_PORT_LACP_ENABLED)) | ||
| 1075 | port->sm_rx_state = AD_RX_EXPIRED; // next state | 1065 | port->sm_rx_state = AD_RX_EXPIRED; // next state |
| 1076 | } else if (port->is_enabled && ((port->sm_vars & AD_PORT_LACP_ENABLED) == 0)) { | 1066 | else if (port->is_enabled |
| 1067 | && ((port->sm_vars | ||
| 1068 | & AD_PORT_LACP_ENABLED) == 0)) | ||
| 1077 | port->sm_rx_state = AD_RX_LACP_DISABLED; // next state | 1069 | port->sm_rx_state = AD_RX_LACP_DISABLED; // next state |
| 1078 | } | ||
| 1079 | break; | 1070 | break; |
| 1080 | default: //to silence the compiler | 1071 | default: //to silence the compiler |
| 1081 | break; | 1072 | break; |
| @@ -1091,11 +1082,10 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
| 1091 | port->sm_rx_state); | 1082 | port->sm_rx_state); |
| 1092 | switch (port->sm_rx_state) { | 1083 | switch (port->sm_rx_state) { |
| 1093 | case AD_RX_INITIALIZE: | 1084 | case AD_RX_INITIALIZE: |
| 1094 | if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) { | 1085 | if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) |
| 1095 | port->sm_vars &= ~AD_PORT_LACP_ENABLED; | 1086 | port->sm_vars &= ~AD_PORT_LACP_ENABLED; |
| 1096 | } else { | 1087 | else |
| 1097 | port->sm_vars |= AD_PORT_LACP_ENABLED; | 1088 | port->sm_vars |= AD_PORT_LACP_ENABLED; |
| 1098 | } | ||
| 1099 | port->sm_vars &= ~AD_PORT_SELECTED; | 1089 | port->sm_vars &= ~AD_PORT_SELECTED; |
| 1100 | __record_default(port); | 1090 | __record_default(port); |
| 1101 | port->actor_oper_port_state &= ~AD_STATE_EXPIRED; | 1091 | port->actor_oper_port_state &= ~AD_STATE_EXPIRED; |
| @@ -1138,7 +1128,6 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
| 1138 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" | 1128 | pr_err("%s: An illegal loopback occurred on adapter (%s).\n" |
| 1139 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", | 1129 | "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", |
| 1140 | port->slave->dev->master->name, port->slave->dev->name); | 1130 | port->slave->dev->master->name, port->slave->dev->name); |
| 1141 | __release_rx_machine_lock(port); | ||
| 1142 | return; | 1131 | return; |
| 1143 | } | 1132 | } |
| 1144 | __update_selected(lacpdu, port); | 1133 | __update_selected(lacpdu, port); |
| @@ -1149,15 +1138,15 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) | |||
| 1149 | // verify that if the aggregator is enabled, the port is enabled too. | 1138 | // verify that if the aggregator is enabled, the port is enabled too. |
| 1150 | //(because if the link goes down for a short time, the 802.3ad will not | 1139 | //(because if the link goes down for a short time, the 802.3ad will not |
| 1151 | // catch it, and the port will continue to be disabled) | 1140 | // catch it, and the port will continue to be disabled) |
| 1152 | if (port->aggregator && port->aggregator->is_active && !__port_is_enabled(port)) { | 1141 | if (port->aggregator |
| 1142 | && port->aggregator->is_active | ||
| 1143 | && !__port_is_enabled(port)) | ||
| 1153 | __enable_port(port); | 1144 | __enable_port(port); |
| 1154 | } | ||
| 1155 | break; | 1145 | break; |
| 1156 | default: //to silence the compiler | 1146 | default: //to silence the compiler |
| 1157 | break; | 1147 | break; |
| 1158 | } | 1148 | } |
| 1159 | } | 1149 | } |
| 1160 | __release_rx_machine_lock(port); | ||
| 1161 | } | 1150 | } |
| 1162 | 1151 | ||
| 1163 | /** | 1152 | /** |
| @@ -1183,7 +1172,8 @@ static void ad_tx_machine(struct port *port) | |||
| 1183 | } | 1172 | } |
| 1184 | } | 1173 | } |
| 1185 | // restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND | 1174 | // restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND |
| 1186 | port->sm_tx_timer_counter=ad_ticks_per_sec/AD_MAX_TX_IN_SECOND; | 1175 | port->sm_tx_timer_counter = |
| 1176 | ad_ticks_per_sec/AD_MAX_TX_IN_SECOND; | ||
| 1187 | } | 1177 | } |
| 1188 | } | 1178 | } |
| 1189 | 1179 | ||
| @@ -1216,9 +1206,9 @@ static void ad_periodic_machine(struct port *port) | |||
| 1216 | // If not expired, check if there is some new timeout parameter from the partner state | 1206 | // If not expired, check if there is some new timeout parameter from the partner state |
| 1217 | switch (port->sm_periodic_state) { | 1207 | switch (port->sm_periodic_state) { |
| 1218 | case AD_FAST_PERIODIC: | 1208 | case AD_FAST_PERIODIC: |
| 1219 | if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) { | 1209 | if (!(port->partner_oper.port_state |
| 1210 | & AD_STATE_LACP_TIMEOUT)) | ||
| 1220 | port->sm_periodic_state = AD_SLOW_PERIODIC; // next state | 1211 | port->sm_periodic_state = AD_SLOW_PERIODIC; // next state |
| 1221 | } | ||
| 1222 | break; | 1212 | break; |
| 1223 | case AD_SLOW_PERIODIC: | 1213 | case AD_SLOW_PERIODIC: |
| 1224 | if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) { | 1214 | if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) { |
| @@ -1237,11 +1227,11 @@ static void ad_periodic_machine(struct port *port) | |||
| 1237 | port->sm_periodic_state = AD_FAST_PERIODIC; // next state | 1227 | port->sm_periodic_state = AD_FAST_PERIODIC; // next state |
| 1238 | break; | 1228 | break; |
| 1239 | case AD_PERIODIC_TX: | 1229 | case AD_PERIODIC_TX: |
| 1240 | if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) { | 1230 | if (!(port->partner_oper.port_state |
| 1231 | & AD_STATE_LACP_TIMEOUT)) | ||
| 1241 | port->sm_periodic_state = AD_SLOW_PERIODIC; // next state | 1232 | port->sm_periodic_state = AD_SLOW_PERIODIC; // next state |
| 1242 | } else { | 1233 | else |
| 1243 | port->sm_periodic_state = AD_FAST_PERIODIC; // next state | 1234 | port->sm_periodic_state = AD_FAST_PERIODIC; // next state |
| 1244 | } | ||
| 1245 | break; | 1235 | break; |
| 1246 | default: //to silence the compiler | 1236 | default: //to silence the compiler |
| 1247 | break; | 1237 | break; |
| @@ -1287,35 +1277,37 @@ static void ad_port_selection_logic(struct port *port) | |||
| 1287 | int found = 0; | 1277 | int found = 0; |
| 1288 | 1278 | ||
| 1289 | // if the port is already Selected, do nothing | 1279 | // if the port is already Selected, do nothing |
| 1290 | if (port->sm_vars & AD_PORT_SELECTED) { | 1280 | if (port->sm_vars & AD_PORT_SELECTED) |
| 1291 | return; | 1281 | return; |
| 1292 | } | ||
| 1293 | 1282 | ||
| 1294 | // if the port is connected to other aggregator, detach it | 1283 | // if the port is connected to other aggregator, detach it |
| 1295 | if (port->aggregator) { | 1284 | if (port->aggregator) { |
| 1296 | // detach the port from its former aggregator | 1285 | // detach the port from its former aggregator |
| 1297 | temp_aggregator=port->aggregator; | 1286 | temp_aggregator = port->aggregator; |
| 1298 | for (curr_port=temp_aggregator->lag_ports; curr_port; last_port=curr_port, curr_port=curr_port->next_port_in_aggregator) { | 1287 | for (curr_port = temp_aggregator->lag_ports; curr_port; |
| 1288 | last_port = curr_port, | ||
| 1289 | curr_port = curr_port->next_port_in_aggregator) { | ||
| 1299 | if (curr_port == port) { | 1290 | if (curr_port == port) { |
| 1300 | temp_aggregator->num_of_ports--; | 1291 | temp_aggregator->num_of_ports--; |
| 1301 | if (!last_port) {// if it is the first port attached to the aggregator | 1292 | if (!last_port) {// if it is the first port attached to the aggregator |
| 1302 | temp_aggregator->lag_ports=port->next_port_in_aggregator; | 1293 | temp_aggregator->lag_ports = |
| 1294 | port->next_port_in_aggregator; | ||
| 1303 | } else {// not the first port attached to the aggregator | 1295 | } else {// not the first port attached to the aggregator |
| 1304 | last_port->next_port_in_aggregator=port->next_port_in_aggregator; | 1296 | last_port->next_port_in_aggregator = |
| 1297 | port->next_port_in_aggregator; | ||
| 1305 | } | 1298 | } |
| 1306 | 1299 | ||
| 1307 | // clear the port's relations to this aggregator | 1300 | // clear the port's relations to this aggregator |
| 1308 | port->aggregator = NULL; | 1301 | port->aggregator = NULL; |
| 1309 | port->next_port_in_aggregator=NULL; | 1302 | port->next_port_in_aggregator = NULL; |
| 1310 | port->actor_port_aggregator_identifier=0; | 1303 | port->actor_port_aggregator_identifier = 0; |
| 1311 | 1304 | ||
| 1312 | pr_debug("Port %d left LAG %d\n", | 1305 | pr_debug("Port %d left LAG %d\n", |
| 1313 | port->actor_port_number, | 1306 | port->actor_port_number, |
| 1314 | temp_aggregator->aggregator_identifier); | 1307 | temp_aggregator->aggregator_identifier); |
| 1315 | // if the aggregator is empty, clear its parameters, and set it ready to be attached | 1308 | // if the aggregator is empty, clear its parameters, and set it ready to be attached |
| 1316 | if (!temp_aggregator->lag_ports) { | 1309 | if (!temp_aggregator->lag_ports) |
| 1317 | ad_clear_agg(temp_aggregator); | 1310 | ad_clear_agg(temp_aggregator); |
| 1318 | } | ||
| 1319 | break; | 1311 | break; |
| 1320 | } | 1312 | } |
| 1321 | } | 1313 | } |
| @@ -1333,9 +1325,8 @@ static void ad_port_selection_logic(struct port *port) | |||
| 1333 | 1325 | ||
| 1334 | // keep a free aggregator for later use(if needed) | 1326 | // keep a free aggregator for later use(if needed) |
| 1335 | if (!aggregator->lag_ports) { | 1327 | if (!aggregator->lag_ports) { |
| 1336 | if (!free_aggregator) { | 1328 | if (!free_aggregator) |
| 1337 | free_aggregator=aggregator; | 1329 | free_aggregator = aggregator; |
| 1338 | } | ||
| 1339 | continue; | 1330 | continue; |
| 1340 | } | 1331 | } |
| 1341 | // check if current aggregator suits us | 1332 | // check if current aggregator suits us |
| @@ -1350,10 +1341,11 @@ static void ad_port_selection_logic(struct port *port) | |||
| 1350 | ) { | 1341 | ) { |
| 1351 | // attach to the founded aggregator | 1342 | // attach to the founded aggregator |
| 1352 | port->aggregator = aggregator; | 1343 | port->aggregator = aggregator; |
| 1353 | port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier; | 1344 | port->actor_port_aggregator_identifier = |
| 1354 | port->next_port_in_aggregator=aggregator->lag_ports; | 1345 | port->aggregator->aggregator_identifier; |
| 1346 | port->next_port_in_aggregator = aggregator->lag_ports; | ||
| 1355 | port->aggregator->num_of_ports++; | 1347 | port->aggregator->num_of_ports++; |
| 1356 | aggregator->lag_ports=port; | 1348 | aggregator->lag_ports = port; |
| 1357 | pr_debug("Port %d joined LAG %d(existing LAG)\n", | 1349 | pr_debug("Port %d joined LAG %d(existing LAG)\n", |
| 1358 | port->actor_port_number, | 1350 | port->actor_port_number, |
| 1359 | port->aggregator->aggregator_identifier); | 1351 | port->aggregator->aggregator_identifier); |
| @@ -1370,20 +1362,23 @@ static void ad_port_selection_logic(struct port *port) | |||
| 1370 | if (free_aggregator) { | 1362 | if (free_aggregator) { |
| 1371 | // assign port a new aggregator | 1363 | // assign port a new aggregator |
| 1372 | port->aggregator = free_aggregator; | 1364 | port->aggregator = free_aggregator; |
| 1373 | port->actor_port_aggregator_identifier=port->aggregator->aggregator_identifier; | 1365 | port->actor_port_aggregator_identifier = |
| 1366 | port->aggregator->aggregator_identifier; | ||
| 1374 | 1367 | ||
| 1375 | // update the new aggregator's parameters | 1368 | // update the new aggregator's parameters |
| 1376 | // if port was responsed from the end-user | 1369 | // if port was responsed from the end-user |
| 1377 | if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) {// if port is full duplex | 1370 | if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) |
| 1371 | /* if port is full duplex */ | ||
| 1378 | port->aggregator->is_individual = false; | 1372 | port->aggregator->is_individual = false; |
| 1379 | } else { | 1373 | else |
| 1380 | port->aggregator->is_individual = true; | 1374 | port->aggregator->is_individual = true; |
| 1381 | } | ||
| 1382 | 1375 | ||
| 1383 | port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key; | 1376 | port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key; |
| 1384 | port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key; | 1377 | port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key; |
| 1385 | port->aggregator->partner_system=port->partner_oper.system; | 1378 | port->aggregator->partner_system = |
| 1386 | port->aggregator->partner_system_priority = port->partner_oper.system_priority; | 1379 | port->partner_oper.system; |
| 1380 | port->aggregator->partner_system_priority = | ||
| 1381 | port->partner_oper.system_priority; | ||
| 1387 | port->aggregator->partner_oper_aggregator_key = port->partner_oper.key; | 1382 | port->aggregator->partner_oper_aggregator_key = port->partner_oper.key; |
| 1388 | port->aggregator->receive_state = 1; | 1383 | port->aggregator->receive_state = 1; |
| 1389 | port->aggregator->transmit_state = 1; | 1384 | port->aggregator->transmit_state = 1; |
| @@ -1485,8 +1480,11 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best, | |||
| 1485 | 1480 | ||
| 1486 | static int agg_device_up(const struct aggregator *agg) | 1481 | static int agg_device_up(const struct aggregator *agg) |
| 1487 | { | 1482 | { |
| 1488 | return (netif_running(agg->slave->dev) && | 1483 | struct port *port = agg->lag_ports; |
| 1489 | netif_carrier_ok(agg->slave->dev)); | 1484 | if (!port) |
| 1485 | return 0; | ||
| 1486 | return (netif_running(port->slave->dev) && | ||
| 1487 | netif_carrier_ok(port->slave->dev)); | ||
| 1490 | } | 1488 | } |
| 1491 | 1489 | ||
| 1492 | /** | 1490 | /** |
| @@ -1704,9 +1702,8 @@ static void ad_initialize_port(struct port *port, int lacp_fast) | |||
| 1704 | port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY; | 1702 | port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY; |
| 1705 | port->actor_oper_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY; | 1703 | port->actor_oper_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY; |
| 1706 | 1704 | ||
| 1707 | if (lacp_fast) { | 1705 | if (lacp_fast) |
| 1708 | port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; | 1706 | port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; |
| 1709 | } | ||
| 1710 | 1707 | ||
| 1711 | memcpy(&port->partner_admin, &tmpl, sizeof(tmpl)); | 1708 | memcpy(&port->partner_admin, &tmpl, sizeof(tmpl)); |
| 1712 | memcpy(&port->partner_oper, &tmpl, sizeof(tmpl)); | 1709 | memcpy(&port->partner_oper, &tmpl, sizeof(tmpl)); |
| @@ -1785,13 +1782,16 @@ static void ad_marker_info_send(struct port *port) | |||
| 1785 | marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8)); | 1782 | marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8)); |
| 1786 | marker.requester_system = port->actor_system; | 1783 | marker.requester_system = port->actor_system; |
| 1787 | // convert requester_port(u32) to Big Endian | 1784 | // convert requester_port(u32) to Big Endian |
| 1788 | marker.requester_transaction_id = (((++port->transaction_id & 0xFF) << 24) |((port->transaction_id & 0xFF00) << 8) |((port->transaction_id & 0xFF0000) >> 8) |((port->transaction_id & 0xFF000000) >> 24)); | 1785 | marker.requester_transaction_id = |
| 1786 | (((++port->transaction_id & 0xFF) << 24) | ||
| 1787 | | ((port->transaction_id & 0xFF00) << 8) | ||
| 1788 | | ((port->transaction_id & 0xFF0000) >> 8) | ||
| 1789 | | ((port->transaction_id & 0xFF000000) >> 24)); | ||
| 1789 | marker.pad = 0; | 1790 | marker.pad = 0; |
| 1790 | marker.tlv_type_terminator = 0x00; | 1791 | marker.tlv_type_terminator = 0x00; |
| 1791 | marker.terminator_length = 0x00; | 1792 | marker.terminator_length = 0x00; |
| 1792 | for (index=0; index<90; index++) { | 1793 | for (index = 0; index < 90; index++) |
| 1793 | marker.reserved_90[index]=0; | 1794 | marker.reserved_90[index] = 0; |
| 1794 | } | ||
| 1795 | 1795 | ||
| 1796 | // send the marker information | 1796 | // send the marker information |
| 1797 | if (ad_marker_send(port, &marker) >= 0) { | 1797 | if (ad_marker_send(port, &marker) >= 0) { |
| @@ -1816,7 +1816,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info, | |||
| 1816 | //marker = *marker_info; | 1816 | //marker = *marker_info; |
| 1817 | memcpy(&marker, marker_info, sizeof(struct bond_marker)); | 1817 | memcpy(&marker, marker_info, sizeof(struct bond_marker)); |
| 1818 | // change the marker subtype to marker response | 1818 | // change the marker subtype to marker response |
| 1819 | marker.tlv_type=AD_MARKER_RESPONSE_SUBTYPE; | 1819 | marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE; |
| 1820 | // send the marker response | 1820 | // send the marker response |
| 1821 | 1821 | ||
| 1822 | if (ad_marker_send(port, &marker) >= 0) { | 1822 | if (ad_marker_send(port, &marker) >= 0) { |
| @@ -1837,8 +1837,8 @@ static void ad_marker_info_received(struct bond_marker *marker_info, | |||
| 1837 | static void ad_marker_response_received(struct bond_marker *marker, | 1837 | static void ad_marker_response_received(struct bond_marker *marker, |
| 1838 | struct port *port) | 1838 | struct port *port) |
| 1839 | { | 1839 | { |
| 1840 | marker=NULL; // just to satisfy the compiler | 1840 | marker = NULL; /* just to satisfy the compiler */ |
| 1841 | port=NULL; // just to satisfy the compiler | 1841 | port = NULL; /* just to satisfy the compiler */ |
| 1842 | // DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW | 1842 | // DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW |
| 1843 | } | 1843 | } |
| 1844 | 1844 | ||
| @@ -1912,7 +1912,7 @@ int bond_3ad_bind_slave(struct slave *slave) | |||
| 1912 | return -1; | 1912 | return -1; |
| 1913 | } | 1913 | } |
| 1914 | 1914 | ||
| 1915 | //check that the slave has not been intialized yet. | 1915 | //check that the slave has not been initialized yet. |
| 1916 | if (SLAVE_AD_INFO(slave).port.slave != slave) { | 1916 | if (SLAVE_AD_INFO(slave).port.slave != slave) { |
| 1917 | 1917 | ||
| 1918 | // port initialization | 1918 | // port initialization |
| @@ -1932,9 +1932,8 @@ int bond_3ad_bind_slave(struct slave *slave) | |||
| 1932 | port->actor_admin_port_key |= (__get_link_speed(port) << 1); | 1932 | port->actor_admin_port_key |= (__get_link_speed(port) << 1); |
| 1933 | port->actor_oper_port_key = port->actor_admin_port_key; | 1933 | port->actor_oper_port_key = port->actor_admin_port_key; |
| 1934 | // if the port is not full duplex, then the port should be not lacp Enabled | 1934 | // if the port is not full duplex, then the port should be not lacp Enabled |
| 1935 | if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) { | 1935 | if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) |
| 1936 | port->sm_vars &= ~AD_PORT_LACP_ENABLED; | 1936 | port->sm_vars &= ~AD_PORT_LACP_ENABLED; |
| 1937 | } | ||
| 1938 | // actor system is the bond's system | 1937 | // actor system is the bond's system |
| 1939 | port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr; | 1938 | port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr; |
| 1940 | // tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second) | 1939 | // tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second) |
| @@ -2006,9 +2005,10 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
| 2006 | new_aggregator = __get_first_agg(port); | 2005 | new_aggregator = __get_first_agg(port); |
| 2007 | for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) { | 2006 | for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) { |
| 2008 | // if the new aggregator is empty, or it is connected to our port only | 2007 | // if the new aggregator is empty, or it is connected to our port only |
| 2009 | if (!new_aggregator->lag_ports || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator)) { | 2008 | if (!new_aggregator->lag_ports |
| 2009 | || ((new_aggregator->lag_ports == port) | ||
| 2010 | && !new_aggregator->lag_ports->next_port_in_aggregator)) | ||
| 2010 | break; | 2011 | break; |
| 2011 | } | ||
| 2012 | } | 2012 | } |
| 2013 | // if new aggregator found, copy the aggregator's parameters | 2013 | // if new aggregator found, copy the aggregator's parameters |
| 2014 | // and connect the related lag_ports to the new aggregator | 2014 | // and connect the related lag_ports to the new aggregator |
| @@ -2037,17 +2037,17 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
| 2037 | new_aggregator->num_of_ports = aggregator->num_of_ports; | 2037 | new_aggregator->num_of_ports = aggregator->num_of_ports; |
| 2038 | 2038 | ||
| 2039 | // update the information that is written on the ports about the aggregator | 2039 | // update the information that is written on the ports about the aggregator |
| 2040 | for (temp_port=aggregator->lag_ports; temp_port; temp_port=temp_port->next_port_in_aggregator) { | 2040 | for (temp_port = aggregator->lag_ports; temp_port; |
| 2041 | temp_port->aggregator=new_aggregator; | 2041 | temp_port = temp_port->next_port_in_aggregator) { |
| 2042 | temp_port->aggregator = new_aggregator; | ||
| 2042 | temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier; | 2043 | temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier; |
| 2043 | } | 2044 | } |
| 2044 | 2045 | ||
| 2045 | // clear the aggregator | 2046 | // clear the aggregator |
| 2046 | ad_clear_agg(aggregator); | 2047 | ad_clear_agg(aggregator); |
| 2047 | 2048 | ||
| 2048 | if (select_new_active_agg) { | 2049 | if (select_new_active_agg) |
| 2049 | ad_agg_selection_logic(__get_first_agg(port)); | 2050 | ad_agg_selection_logic(__get_first_agg(port)); |
| 2050 | } | ||
| 2051 | } else { | 2051 | } else { |
| 2052 | pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n", | 2052 | pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n", |
| 2053 | slave->dev->master->name); | 2053 | slave->dev->master->name); |
| @@ -2071,15 +2071,16 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
| 2071 | for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) { | 2071 | for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) { |
| 2072 | prev_port = NULL; | 2072 | prev_port = NULL; |
| 2073 | // search the port in the aggregator's related ports | 2073 | // search the port in the aggregator's related ports |
| 2074 | for (temp_port=temp_aggregator->lag_ports; temp_port; prev_port=temp_port, temp_port=temp_port->next_port_in_aggregator) { | 2074 | for (temp_port = temp_aggregator->lag_ports; temp_port; |
| 2075 | prev_port = temp_port, | ||
| 2076 | temp_port = temp_port->next_port_in_aggregator) { | ||
| 2075 | if (temp_port == port) { // the aggregator found - detach the port from this aggregator | 2077 | if (temp_port == port) { // the aggregator found - detach the port from this aggregator |
| 2076 | if (prev_port) { | 2078 | if (prev_port) |
| 2077 | prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator; | 2079 | prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator; |
| 2078 | } else { | 2080 | else |
| 2079 | temp_aggregator->lag_ports = temp_port->next_port_in_aggregator; | 2081 | temp_aggregator->lag_ports = temp_port->next_port_in_aggregator; |
| 2080 | } | ||
| 2081 | temp_aggregator->num_of_ports--; | 2082 | temp_aggregator->num_of_ports--; |
| 2082 | if (temp_aggregator->num_of_ports==0) { | 2083 | if (temp_aggregator->num_of_ports == 0) { |
| 2083 | select_new_active_agg = temp_aggregator->is_active; | 2084 | select_new_active_agg = temp_aggregator->is_active; |
| 2084 | // clear the aggregator | 2085 | // clear the aggregator |
| 2085 | ad_clear_agg(temp_aggregator); | 2086 | ad_clear_agg(temp_aggregator); |
| @@ -2094,7 +2095,7 @@ void bond_3ad_unbind_slave(struct slave *slave) | |||
| 2094 | } | 2095 | } |
| 2095 | } | 2096 | } |
| 2096 | } | 2097 | } |
| 2097 | port->slave=NULL; | 2098 | port->slave = NULL; |
| 2098 | } | 2099 | } |
| 2099 | 2100 | ||
| 2100 | /** | 2101 | /** |
| @@ -2119,14 +2120,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
| 2119 | 2120 | ||
| 2120 | read_lock(&bond->lock); | 2121 | read_lock(&bond->lock); |
| 2121 | 2122 | ||
| 2122 | if (bond->kill_timers) { | 2123 | if (bond->kill_timers) |
| 2123 | goto out; | 2124 | goto out; |
| 2124 | } | ||
| 2125 | 2125 | ||
| 2126 | //check if there are any slaves | 2126 | //check if there are any slaves |
| 2127 | if (bond->slave_cnt == 0) { | 2127 | if (bond->slave_cnt == 0) |
| 2128 | goto re_arm; | 2128 | goto re_arm; |
| 2129 | } | ||
| 2130 | 2129 | ||
| 2131 | // check if agg_select_timer timer after initialize is timed out | 2130 | // check if agg_select_timer timer after initialize is timed out |
| 2132 | if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) { | 2131 | if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) { |
| @@ -2152,6 +2151,12 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
| 2152 | goto re_arm; | 2151 | goto re_arm; |
| 2153 | } | 2152 | } |
| 2154 | 2153 | ||
| 2154 | /* Lock around state machines to protect data accessed | ||
| 2155 | * by all (e.g., port->sm_vars). ad_rx_machine may run | ||
| 2156 | * concurrently due to incoming LACPDU. | ||
| 2157 | */ | ||
| 2158 | __get_state_machine_lock(port); | ||
| 2159 | |||
| 2155 | ad_rx_machine(NULL, port); | 2160 | ad_rx_machine(NULL, port); |
| 2156 | ad_periodic_machine(port); | 2161 | ad_periodic_machine(port); |
| 2157 | ad_port_selection_logic(port); | 2162 | ad_port_selection_logic(port); |
| @@ -2159,9 +2164,10 @@ void bond_3ad_state_machine_handler(struct work_struct *work) | |||
| 2159 | ad_tx_machine(port); | 2164 | ad_tx_machine(port); |
| 2160 | 2165 | ||
| 2161 | // turn off the BEGIN bit, since we already handled it | 2166 | // turn off the BEGIN bit, since we already handled it |
| 2162 | if (port->sm_vars & AD_PORT_BEGIN) { | 2167 | if (port->sm_vars & AD_PORT_BEGIN) |
| 2163 | port->sm_vars &= ~AD_PORT_BEGIN; | 2168 | port->sm_vars &= ~AD_PORT_BEGIN; |
| 2164 | } | 2169 | |
| 2170 | __release_state_machine_lock(port); | ||
| 2165 | } | 2171 | } |
| 2166 | 2172 | ||
| 2167 | re_arm: | 2173 | re_arm: |
| @@ -2198,7 +2204,10 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u | |||
| 2198 | case AD_TYPE_LACPDU: | 2204 | case AD_TYPE_LACPDU: |
| 2199 | pr_debug("Received LACPDU on port %d\n", | 2205 | pr_debug("Received LACPDU on port %d\n", |
| 2200 | port->actor_port_number); | 2206 | port->actor_port_number); |
| 2207 | /* Protect against concurrent state machines */ | ||
| 2208 | __get_state_machine_lock(port); | ||
| 2201 | ad_rx_machine(lacpdu, port); | 2209 | ad_rx_machine(lacpdu, port); |
| 2210 | __release_state_machine_lock(port); | ||
| 2202 | break; | 2211 | break; |
| 2203 | 2212 | ||
| 2204 | case AD_TYPE_MARKER: | 2213 | case AD_TYPE_MARKER: |
| @@ -2245,7 +2254,8 @@ void bond_3ad_adapter_speed_changed(struct slave *slave) | |||
| 2245 | } | 2254 | } |
| 2246 | 2255 | ||
| 2247 | port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; | 2256 | port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; |
| 2248 | port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1); | 2257 | port->actor_oper_port_key = port->actor_admin_port_key |= |
| 2258 | (__get_link_speed(port) << 1); | ||
| 2249 | pr_debug("Port %d changed speed\n", port->actor_port_number); | 2259 | pr_debug("Port %d changed speed\n", port->actor_port_number); |
| 2250 | // there is no need to reselect a new aggregator, just signal the | 2260 | // there is no need to reselect a new aggregator, just signal the |
| 2251 | // state machines to reinitialize | 2261 | // state machines to reinitialize |
| @@ -2262,7 +2272,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) | |||
| 2262 | { | 2272 | { |
| 2263 | struct port *port; | 2273 | struct port *port; |
| 2264 | 2274 | ||
| 2265 | port=&(SLAVE_AD_INFO(slave).port); | 2275 | port = &(SLAVE_AD_INFO(slave).port); |
| 2266 | 2276 | ||
| 2267 | // if slave is null, the whole port is not initialized | 2277 | // if slave is null, the whole port is not initialized |
| 2268 | if (!port->slave) { | 2278 | if (!port->slave) { |
| @@ -2272,7 +2282,8 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave) | |||
| 2272 | } | 2282 | } |
| 2273 | 2283 | ||
| 2274 | port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; | 2284 | port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; |
| 2275 | port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port); | 2285 | port->actor_oper_port_key = port->actor_admin_port_key |= |
| 2286 | __get_duplex(port); | ||
| 2276 | pr_debug("Port %d changed duplex\n", port->actor_port_number); | 2287 | pr_debug("Port %d changed duplex\n", port->actor_port_number); |
| 2277 | // there is no need to reselect a new aggregator, just signal the | 2288 | // there is no need to reselect a new aggregator, just signal the |
| 2278 | // state machines to reinitialize | 2289 | // state machines to reinitialize |
| @@ -2304,14 +2315,17 @@ void bond_3ad_handle_link_change(struct slave *slave, char link) | |||
| 2304 | if (link == BOND_LINK_UP) { | 2315 | if (link == BOND_LINK_UP) { |
| 2305 | port->is_enabled = true; | 2316 | port->is_enabled = true; |
| 2306 | port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; | 2317 | port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; |
| 2307 | port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port); | 2318 | port->actor_oper_port_key = port->actor_admin_port_key |= |
| 2319 | __get_duplex(port); | ||
| 2308 | port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; | 2320 | port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS; |
| 2309 | port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1); | 2321 | port->actor_oper_port_key = port->actor_admin_port_key |= |
| 2322 | (__get_link_speed(port) << 1); | ||
| 2310 | } else { | 2323 | } else { |
| 2311 | /* link has failed */ | 2324 | /* link has failed */ |
| 2312 | port->is_enabled = false; | 2325 | port->is_enabled = false; |
| 2313 | port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; | 2326 | port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS; |
| 2314 | port->actor_oper_port_key= (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS); | 2327 | port->actor_oper_port_key = (port->actor_admin_port_key &= |
| 2328 | ~AD_SPEED_KEY_BITS); | ||
| 2315 | } | 2329 | } |
| 2316 | //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN"))); | 2330 | //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN"))); |
| 2317 | // there is no need to reselect a new aggregator, just signal the | 2331 | // there is no need to reselect a new aggregator, just signal the |
| @@ -2389,15 +2403,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) | |||
| 2389 | struct ad_info ad_info; | 2403 | struct ad_info ad_info; |
| 2390 | int res = 1; | 2404 | int res = 1; |
| 2391 | 2405 | ||
| 2392 | /* make sure that the slaves list will | ||
| 2393 | * not change during tx | ||
| 2394 | */ | ||
| 2395 | read_lock(&bond->lock); | ||
| 2396 | |||
| 2397 | if (!BOND_IS_OK(bond)) { | ||
| 2398 | goto out; | ||
| 2399 | } | ||
| 2400 | |||
| 2401 | if (bond_3ad_get_active_agg_info(bond, &ad_info)) { | 2406 | if (bond_3ad_get_active_agg_info(bond, &ad_info)) { |
| 2402 | pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n", | 2407 | pr_debug("%s: Error: bond_3ad_get_active_agg_info failed\n", |
| 2403 | dev->name); | 2408 | dev->name); |
| @@ -2420,9 +2425,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) | |||
| 2420 | 2425 | ||
| 2421 | if (agg && (agg->aggregator_identifier == agg_id)) { | 2426 | if (agg && (agg->aggregator_identifier == agg_id)) { |
| 2422 | slave_agg_no--; | 2427 | slave_agg_no--; |
| 2423 | if (slave_agg_no < 0) { | 2428 | if (slave_agg_no < 0) |
| 2424 | break; | 2429 | break; |
| 2425 | } | ||
| 2426 | } | 2430 | } |
| 2427 | } | 2431 | } |
| 2428 | 2432 | ||
| @@ -2438,9 +2442,8 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) | |||
| 2438 | int slave_agg_id = 0; | 2442 | int slave_agg_id = 0; |
| 2439 | struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; | 2443 | struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; |
| 2440 | 2444 | ||
| 2441 | if (agg) { | 2445 | if (agg) |
| 2442 | slave_agg_id = agg->aggregator_identifier; | 2446 | slave_agg_id = agg->aggregator_identifier; |
| 2443 | } | ||
| 2444 | 2447 | ||
| 2445 | if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) { | 2448 | if (SLAVE_IS_OK(slave) && agg && (slave_agg_id == agg_id)) { |
| 2446 | res = bond_dev_queue_xmit(bond, skb, slave->dev); | 2449 | res = bond_dev_queue_xmit(bond, skb, slave->dev); |
| @@ -2453,36 +2456,20 @@ out: | |||
| 2453 | /* no suitable interface, frame not sent */ | 2456 | /* no suitable interface, frame not sent */ |
| 2454 | dev_kfree_skb(skb); | 2457 | dev_kfree_skb(skb); |
| 2455 | } | 2458 | } |
| 2456 | read_unlock(&bond->lock); | 2459 | |
| 2457 | return NETDEV_TX_OK; | 2460 | return NETDEV_TX_OK; |
| 2458 | } | 2461 | } |
| 2459 | 2462 | ||
| 2460 | int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev) | 2463 | void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, |
| 2464 | struct slave *slave) | ||
| 2461 | { | 2465 | { |
| 2462 | struct bonding *bond = netdev_priv(dev); | 2466 | if (skb->protocol != PKT_TYPE_LACPDU) |
| 2463 | struct slave *slave = NULL; | 2467 | return; |
| 2464 | int ret = NET_RX_DROP; | ||
| 2465 | |||
| 2466 | if (!(dev->flags & IFF_MASTER)) | ||
| 2467 | goto out; | ||
| 2468 | 2468 | ||
| 2469 | if (!pskb_may_pull(skb, sizeof(struct lacpdu))) | 2469 | if (!pskb_may_pull(skb, sizeof(struct lacpdu))) |
| 2470 | goto out; | 2470 | return; |
| 2471 | 2471 | ||
| 2472 | read_lock(&bond->lock); | 2472 | read_lock(&bond->lock); |
| 2473 | slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev), | ||
| 2474 | orig_dev); | ||
| 2475 | if (!slave) | ||
| 2476 | goto out_unlock; | ||
| 2477 | |||
| 2478 | bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len); | 2473 | bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len); |
| 2479 | |||
| 2480 | ret = NET_RX_SUCCESS; | ||
| 2481 | |||
| 2482 | out_unlock: | ||
| 2483 | read_unlock(&bond->lock); | 2474 | read_unlock(&bond->lock); |
| 2484 | out: | ||
| 2485 | dev_kfree_skb(skb); | ||
| 2486 | |||
| 2487 | return ret; | ||
| 2488 | } | 2475 | } |
