Skip to content

Commit

Permalink
bonding: don't increase rx_dropped after processing LACPDUs
Browse files Browse the repository at this point in the history
Since commit 3aba891, 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: Jiri Bohac <jbohac@suse.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jiri Bohac authored and David S. Miller committed May 11, 2012
1 parent 38bf195 commit 13a8e0c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
18 changes: 12 additions & 6 deletions drivers/net/bonding/bond_3ad.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
* 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;
int ret = RX_HANDLER_ANOTHER;

if (length >= sizeof(struct lacpdu)) {

Expand All @@ -2184,11 +2185,12 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
if (!port->slave) {
pr_warning("%s: Warning: port of slave %s is uninitialized\n",
slave->dev->name, slave->dev->master->name);
return;
return ret;
}

switch (lacpdu->subtype) {
case AD_TYPE_LACPDU:
ret = RX_HANDLER_CONSUMED;
pr_debug("Received LACPDU on port %d\n",
port->actor_port_number);
/* Protect against concurrent state machines */
Expand All @@ -2198,6 +2200,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
break;

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.

switch (((struct bond_marker *)lacpdu)->tlv_type) {
Expand All @@ -2219,6 +2222,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
}
}
}
return ret;
}

/**
Expand Down Expand Up @@ -2456,18 +2460,20 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
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)
{
int ret = RX_HANDLER_ANOTHER;
if (skb->protocol != PKT_TYPE_LACPDU)
return;
return ret;

if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
return;
return ret;

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);
return ret;
}

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/bonding/bond_3ad.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave);
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_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);
int bond_3ad_set_carrier(struct bonding *bond);
void bond_3ad_update_lacp_rate(struct bonding *bond);
Expand Down
16 changes: 11 additions & 5 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1444,8 +1444,9 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
struct sk_buff *skb = *pskb;
struct slave *slave;
struct bonding *bond;
void (*recv_probe)(struct sk_buff *, struct bonding *,
int (*recv_probe)(struct sk_buff *, struct bonding *,
struct slave *);
int ret = RX_HANDLER_ANOTHER;

skb = skb_share_check(skb, GFP_ATOMIC);
if (unlikely(!skb))
Expand All @@ -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);

if (likely(nskb)) {
recv_probe(nskb, bond, slave);
ret = recv_probe(nskb, bond, slave);
dev_kfree_skb(nskb);
if (ret == RX_HANDLER_CONSUMED) {
consume_skb(skb);
return ret;
}
}
}

Expand All @@ -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);
}

return RX_HANDLER_ANOTHER;
return ret;
}

/* enslave device <slave> to bond device <master> */
Expand Down Expand Up @@ -2723,15 +2728,15 @@ 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 arphdr *arp;
unsigned char *arp_ptr;
__be32 sip, tip;

if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
return;
return RX_HANDLER_ANOTHER;

read_lock(&bond->lock);

Expand Down Expand Up @@ -2776,6 +2781,7 @@ static void bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,

out_unlock:
read_unlock(&bond->lock);
return RX_HANDLER_ANOTHER;
}

/*
Expand Down

0 comments on commit 13a8e0c

Please sign in to comment.