📄 bond_3ad.c
字号:
// and the parser/multiplexer of the aggregator are already combined}/** * __detach_bond_from_agg * @port: the port we're looking at * * Handle the detaching of the port's control parser/multiplexer from the * aggregator. This function does nothing since the parser/multiplexer of the * receive and the parser/multiplexer of the aggregator are already combined. */static void __detach_bond_from_agg(struct port *port){ port=NULL; // just to satisfy the compiler // This function does nothing sience the parser/multiplexer of the receive // and the parser/multiplexer of the aggregator are already combined}/** * __agg_ports_are_ready - check if all ports in an aggregator are ready * @aggregator: the aggregator we're looking at * */static int __agg_ports_are_ready(struct aggregator *aggregator){ struct port *port; int retval = 1; if (aggregator) { // scan all ports in this aggregator to verfy if they are all ready for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) { if (!(port->sm_vars & AD_PORT_READY_N)) { retval = 0; break; } } } return retval;}/** * __set_agg_ports_ready - set value of Ready bit in all ports of an aggregator * @aggregator: the aggregator we're looking at * @val: Should the ports' ready bit be set on or off * */static void __set_agg_ports_ready(struct aggregator *aggregator, int val){ struct port *port; for (port=aggregator->lag_ports; port; port=port->next_port_in_aggregator) { if (val) { port->sm_vars |= AD_PORT_READY; } else { port->sm_vars &= ~AD_PORT_READY; } }}/** * __get_agg_bandwidth - get the total bandwidth of an aggregator * @aggregator: the aggregator we're looking at * */static u32 __get_agg_bandwidth(struct aggregator *aggregator){ u32 bandwidth=0; u32 basic_speed; if (aggregator->num_of_ports) { basic_speed = __get_link_speed(aggregator->lag_ports); switch (basic_speed) { case AD_LINK_SPEED_BITMASK_1MBPS: bandwidth = aggregator->num_of_ports; break; case AD_LINK_SPEED_BITMASK_10MBPS: bandwidth = aggregator->num_of_ports * 10; break; case AD_LINK_SPEED_BITMASK_100MBPS: bandwidth = aggregator->num_of_ports * 100; break; case AD_LINK_SPEED_BITMASK_1000MBPS: bandwidth = aggregator->num_of_ports * 1000; break; default: bandwidth=0; // to silent the compilor .... } } return bandwidth;}/** * __get_active_agg - get the current active aggregator * @aggregator: the aggregator we're looking at * */static struct aggregator *__get_active_agg(struct aggregator *aggregator){ struct aggregator *retval = NULL; for (; aggregator; aggregator = __get_next_agg(aggregator)) { if (aggregator->is_active) { retval = aggregator; break; } } return retval;}/** * __update_lacpdu_from_port - update a port's lacpdu fields * @port: the port we're looking at * */static inline void __update_lacpdu_from_port(struct port *port){ struct lacpdu *lacpdu = &port->lacpdu; /* update current actual Actor parameters */ /* lacpdu->subtype initialized * lacpdu->version_number initialized * lacpdu->tlv_type_actor_info initialized * lacpdu->actor_information_length initialized */ lacpdu->actor_system_priority = port->actor_system_priority; lacpdu->actor_system = port->actor_system; lacpdu->actor_key = port->actor_oper_port_key; lacpdu->actor_port_priority = port->actor_port_priority; lacpdu->actor_port = port->actor_port_number; lacpdu->actor_state = port->actor_oper_port_state; /* lacpdu->reserved_3_1 initialized * lacpdu->tlv_type_partner_info initialized * lacpdu->partner_information_length initialized */ lacpdu->partner_system_priority = port->partner_oper_system_priority; lacpdu->partner_system = port->partner_oper_system; lacpdu->partner_key = port->partner_oper_key; lacpdu->partner_port_priority = port->partner_oper_port_priority; lacpdu->partner_port = port->partner_oper_port_number; lacpdu->partner_state = port->partner_oper_port_state; /* lacpdu->reserved_3_2 initialized * lacpdu->tlv_type_collector_info initialized * lacpdu->collector_information_length initialized * collector_max_delay initialized * reserved_12[12] initialized * tlv_type_terminator initialized * terminator_length initialized * reserved_50[50] initialized */ /* Convert all non u8 parameters to Big Endian for transmit */ __ntohs_lacpdu(lacpdu);}//////////////////////////////////////////////////////////////////////////////////////// ================= main 802.3ad protocol code ======================================///////////////////////////////////////////////////////////////////////////////////////** * ad_lacpdu_send - send out a lacpdu packet on a given port * @port: the port we're looking at * * Returns: 0 on success * < 0 on error */static int ad_lacpdu_send(struct port *port){ struct slave *slave = port->slave; struct sk_buff *skb; struct lacpdu_header *lacpdu_header; int length = sizeof(struct lacpdu_header); struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR; skb = dev_alloc_skb(length); if (!skb) { return -ENOMEM; } skb->dev = slave->dev; skb->mac.raw = skb->data; skb->nh.raw = skb->data + ETH_HLEN; skb->protocol = PKT_TYPE_LACPDU; skb->priority = TC_PRIO_CONTROL; lacpdu_header = (struct lacpdu_header *)skb_put(skb, length); lacpdu_header->ad_header.destination_address = lacpdu_multicast_address; /* Note: source addres is set to be the member's PERMANENT address, because we use it to identify loopback lacpdus in receive. */ lacpdu_header->ad_header.source_address = *((struct mac_addr *)(slave->perm_hwaddr)); lacpdu_header->ad_header.length_type = PKT_TYPE_LACPDU; lacpdu_header->lacpdu = port->lacpdu; // struct copy dev_queue_xmit(skb); return 0;}/** * ad_marker_send - send marker information/response on a given port * @port: the port we're looking at * @marker: marker data to send * * Returns: 0 on success * < 0 on error */static int ad_marker_send(struct port *port, struct marker *marker){ struct slave *slave = port->slave; struct sk_buff *skb; struct marker_header *marker_header; int length = sizeof(struct marker_header); struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR; skb = dev_alloc_skb(length + 16); if (!skb) { return -ENOMEM; } skb_reserve(skb, 16); skb->dev = slave->dev; skb->mac.raw = skb->data; skb->nh.raw = skb->data + ETH_HLEN; skb->protocol = PKT_TYPE_LACPDU; marker_header = (struct marker_header *)skb_put(skb, length); marker_header->ad_header.destination_address = lacpdu_multicast_address; /* Note: source addres is set to be the member's PERMANENT address, because we use it to identify loopback MARKERs in receive. */ marker_header->ad_header.source_address = *((struct mac_addr *)(slave->perm_hwaddr)); marker_header->ad_header.length_type = PKT_TYPE_LACPDU; marker_header->marker = *marker; // struct copy dev_queue_xmit(skb); return 0;}/** * ad_mux_machine - handle a port's mux state machine * @port: the port we're looking at * */static void ad_mux_machine(struct port *port){ mux_states_t last_state; // keep current State Machine state to compare later if it was changed last_state = port->sm_mux_state; if (port->sm_vars & AD_PORT_BEGIN) { port->sm_mux_state = AD_MUX_DETACHED; // next state } else { switch (port->sm_mux_state) { case AD_MUX_DETACHED: if ((port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if SELECTED or STANDBY port->sm_mux_state = AD_MUX_WAITING; // next state } break; case AD_MUX_WAITING: // if SELECTED == FALSE return to DETACH state if (!(port->sm_vars & AD_PORT_SELECTED)) { // if UNSELECTED port->sm_vars &= ~AD_PORT_READY_N; // in order to withhold the Selection Logic to check all ports READY_N value // every callback cycle to update ready variable, we check READY_N and update READY here __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); port->sm_mux_state = AD_MUX_DETACHED; // next state break; } // check if the wait_while_timer expired if (port->sm_mux_timer_counter && !(--port->sm_mux_timer_counter)) { port->sm_vars |= AD_PORT_READY_N; } // in order to withhold the selection logic to check all ports READY_N value // every callback cycle to update ready variable, we check READY_N and update READY here __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); // if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state if ((port->sm_vars & AD_PORT_READY) && !port->sm_mux_timer_counter) { port->sm_mux_state = AD_MUX_ATTACHED; // next state } break; case AD_MUX_ATTACHED: // check also if agg_select_timer expired(so the edable port will take place only after this timer) if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper_port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) { port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state } else if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if UNSELECTED or STANDBY port->sm_vars &= ~AD_PORT_READY_N; // in order to withhold the selection logic to check all ports READY_N value // every callback cycle to update ready variable, we check READY_N and update READY here __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator)); port->sm_mux_state = AD_MUX_DETACHED;// next state } break; case AD_MUX_COLLECTING_DISTRIBUTING: if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) || !(port->partner_oper_port_state & AD_STATE_SYNCHRONIZATION) ) { port->sm_mux_state = AD_MUX_ATTACHED;// next state } else { // if port state hasn't changed make // sure that a collecting distributing // port in an active aggregator is enabled if (port->aggregator && port->aggregator->is_active && !__port_is_enabled(port)) { __enable_port(port); } } break; default: //to silence the compiler break; } } // check if the state machine was changed if (port->sm_mux_state != last_state) { dprintk("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state); switch (port->sm_mux_state) { case AD_MUX_DETACHED: __detach_bond_from_agg(port); port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; ad_disable_collecting_distributing(port); port->actor_oper_port_state &= ~AD_STATE_COLLECTING; port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; port->ntt = 1; break; case AD_MUX_WAITING: port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0); break; case AD_MUX_ATTACHED: __attach_bond_to_agg(port); port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; port->actor_oper_port_state &= ~AD_STATE_COLLECTING; port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; ad_disable_collecting_distributing(port); port->ntt = 1; break; case AD_MUX_COLLECTING_DISTRIBUTING: port->actor_oper_port_state |= AD_STATE_COLLECTING; port->actor_oper_port_state |= AD_STATE_DISTRIBUTING; ad_enable_collecting_distributing(port); port->ntt = 1; break; default: //to silence the compiler break; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -