Commit 13a8e0c8 authored by Jiri Bohac's avatar Jiri Bohac Committed by David S. Miller

bonding: don't increase rx_dropped after processing LACPDUs

Since commit 3aba891d, bonding processes LACP frames (802.3ad
mode) with bond_handle_frame(). Currently a copy of the skb is
made and the original is left to be processed by other
rx_handlers and the rest of the network stack by returning
RX_HANDLER_ANOTHER.  As there is no protocol handler for
PKT_TYPE_LACPDU, the frame is dropped and dev->rx_dropped
increased.

Fix this by making bond_handle_frame() return RX_HANDLER_CONSUMED
if bonding has processed the LACP frame.
Signed-off-by: default avatarJiri Bohac <jbohac@suse.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 38bf1953
...@@ -2173,9 +2173,10 @@ void bond_3ad_state_machine_handler(struct work_struct *work) ...@@ -2173,9 +2173,10 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
* received frames (loopback). Since only the payload is given to this * received frames (loopback). Since only the payload is given to this
* function, it check for loopback. * function, it check for loopback.
*/ */
static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length) static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
{ {
struct port *port; struct port *port;
int ret = RX_HANDLER_ANOTHER;
if (length >= sizeof(struct lacpdu)) { if (length >= sizeof(struct lacpdu)) {
...@@ -2184,11 +2185,12 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u ...@@ -2184,11 +2185,12 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
if (!port->slave) { if (!port->slave) {
pr_warning("%s: Warning: port of slave %s is uninitialized\n", pr_warning("%s: Warning: port of slave %s is uninitialized\n",
slave->dev->name, slave->dev->master->name); slave->dev->name, slave->dev->master->name);
return; return ret;
} }
switch (lacpdu->subtype) { switch (lacpdu->subtype) {
case AD_TYPE_LACPDU: case AD_TYPE_LACPDU:
ret = RX_HANDLER_CONSUMED;
pr_debug("Received LACPDU on port %d\n", pr_debug("Received LACPDU on port %d\n",
port->actor_port_number); port->actor_port_number);
/* Protect against concurrent state machines */ /* Protect against concurrent state machines */
...@@ -2198,6 +2200,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u ...@@ -2198,6 +2200,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
break; break;
case AD_TYPE_MARKER: case AD_TYPE_MARKER:
ret = RX_HANDLER_CONSUMED;
// No need to convert fields to Little Endian since we don't use the marker's fields. // No need to convert fields to Little Endian since we don't use the marker's fields.
switch (((struct bond_marker *)lacpdu)->tlv_type) { switch (((struct bond_marker *)lacpdu)->tlv_type) {
...@@ -2219,6 +2222,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u ...@@ -2219,6 +2222,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
} }
} }
} }
return ret;
} }
/** /**
...@@ -2456,18 +2460,20 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev) ...@@ -2456,18 +2460,20 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave) struct slave *slave)
{ {
int ret = RX_HANDLER_ANOTHER;
if (skb->protocol != PKT_TYPE_LACPDU) if (skb->protocol != PKT_TYPE_LACPDU)
return; return ret;
if (!pskb_may_pull(skb, sizeof(struct lacpdu))) if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
return; return ret;
read_lock(&bond->lock); read_lock(&bond->lock);
bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len); ret = bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
read_unlock(&bond->lock); read_unlock(&bond->lock);
return ret;
} }
/* /*
......
...@@ -274,7 +274,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave); ...@@ -274,7 +274,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link); void bond_3ad_handle_link_change(struct slave *slave, char link);
int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info); int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev); int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond, int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave); struct slave *slave);
int bond_3ad_set_carrier(struct bonding *bond); int bond_3ad_set_carrier(struct bonding *bond);
void bond_3ad_update_lacp_rate(struct bonding *bond); void bond_3ad_update_lacp_rate(struct bonding *bond);
......
...@@ -1444,8 +1444,9 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) ...@@ -1444,8 +1444,9 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct slave *slave; struct slave *slave;
struct bonding *bond; struct bonding *bond;
void (*recv_probe)(struct sk_buff *, struct bonding *, int (*recv_probe)(struct sk_buff *, struct bonding *,
struct slave *); struct slave *);
int ret = RX_HANDLER_ANOTHER;
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb)) if (unlikely(!skb))
...@@ -1464,8 +1465,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) ...@@ -1464,8 +1465,12 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
if (likely(nskb)) { if (likely(nskb)) {
recv_probe(nskb, bond, slave); ret = recv_probe(nskb, bond, slave);
dev_kfree_skb(nskb); dev_kfree_skb(nskb);
if (ret == RX_HANDLER_CONSUMED) {
consume_skb(skb);
return ret;
}
} }
} }
...@@ -1487,7 +1492,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb) ...@@ -1487,7 +1492,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN); memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
} }
return RX_HANDLER_ANOTHER; return ret;
} }
/* enslave device <slave> to bond device <master> */ /* enslave device <slave> to bond device <master> */
...@@ -2723,7 +2728,7 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 ...@@ -2723,7 +2728,7 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
} }
} }
static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond, static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave) struct slave *slave)
{ {
struct arphdr *arp; struct arphdr *arp;
...@@ -2731,7 +2736,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond, ...@@ -2731,7 +2736,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
__be32 sip, tip; __be32 sip, tip;
if (skb->protocol != __cpu_to_be16(ETH_P_ARP)) if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
return; return RX_HANDLER_ANOTHER;
read_lock(&bond->lock); read_lock(&bond->lock);
...@@ -2776,6 +2781,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond, ...@@ -2776,6 +2781,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
out_unlock: out_unlock:
read_unlock(&bond->lock); read_unlock(&bond->lock);
return RX_HANDLER_ANOTHER;
} }
/* /*
......
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