Commit de063b7040dcd9fbc9a1847fa44f0af13e19d6de

Authored by Eric Dumazet
Committed by David S. Miller
1 parent 072c0559e2

bonding: remove packet cloning in recv_probe()

Cloning all packets in input path have a significant cost.

Use skb_header_pointer()/skb_copy_bits() instead of pskb_may_pull() so
that recv_probe handlers (bond_3ad_lacpdu_recv / bond_arp_rcv /
rlb_arp_recv ) dont touch input skb.

bond_handle_frame() can avoid the skb_clone()/dev_kfree_skb()

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Jay Vosburgh <fubar@us.ibm.com>
Cc: Andy Gospodarek <andy@greyhouse.net>
Cc: Jiri Bohac <jbohac@suse.cz>
Cc: Nicolas de Pesloüan <nicolas.2p.debian@free.fr>
Cc: Maciej Żenczykowski <maze@google.com>
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 5 changed files with 36 additions and 40 deletions Side-by-side Diff

drivers/net/bonding/bond_3ad.c
... ... @@ -2460,18 +2460,21 @@
2460 2460 return NETDEV_TX_OK;
2461 2461 }
2462 2462  
2463   -int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
2464   - struct slave *slave)
  2463 +int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
  2464 + struct slave *slave)
2465 2465 {
2466 2466 int ret = RX_HANDLER_ANOTHER;
  2467 + struct lacpdu *lacpdu, _lacpdu;
  2468 +
2467 2469 if (skb->protocol != PKT_TYPE_LACPDU)
2468 2470 return ret;
2469 2471  
2470   - if (!pskb_may_pull(skb, sizeof(struct lacpdu)))
  2472 + lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu);
  2473 + if (!lacpdu)
2471 2474 return ret;
2472 2475  
2473 2476 read_lock(&bond->lock);
2474   - ret = bond_3ad_rx_indication((struct lacpdu *) skb->data, slave, skb->len);
  2477 + ret = bond_3ad_rx_indication(lacpdu, slave, skb->len);
2475 2478 read_unlock(&bond->lock);
2476 2479 return ret;
2477 2480 }
drivers/net/bonding/bond_3ad.h
... ... @@ -274,8 +274,8 @@
274 274 void bond_3ad_handle_link_change(struct slave *slave, char link);
275 275 int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
276 276 int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
277   -int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
278   - struct slave *slave);
  277 +int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
  278 + struct slave *slave);
279 279 int bond_3ad_set_carrier(struct bonding *bond);
280 280 void bond_3ad_update_lacp_rate(struct bonding *bond);
281 281 #endif //__BOND_3AD_H__
drivers/net/bonding/bond_alb.c
... ... @@ -342,27 +342,17 @@
342 342 _unlock_rx_hashtbl_bh(bond);
343 343 }
344 344  
345   -static int rlb_arp_recv(struct sk_buff *skb, struct bonding *bond,
346   - struct slave *slave)
  345 +static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
  346 + struct slave *slave)
347 347 {
348   - struct arp_pkt *arp;
  348 + struct arp_pkt *arp, _arp;
349 349  
350 350 if (skb->protocol != cpu_to_be16(ETH_P_ARP))
351 351 goto out;
352 352  
353   - arp = (struct arp_pkt *) skb->data;
354   - if (!arp) {
355   - pr_debug("Packet has no ARP data\n");
  353 + arp = skb_header_pointer(skb, 0, sizeof(_arp), &_arp);
  354 + if (!arp)
356 355 goto out;
357   - }
358   -
359   - if (!pskb_may_pull(skb, arp_hdr_len(bond->dev)))
360   - goto out;
361   -
362   - if (skb->len < sizeof(struct arp_pkt)) {
363   - pr_debug("Packet is too small to be an ARP\n");
364   - goto out;
365   - }
366 356  
367 357 if (arp->op_code == htons(ARPOP_REPLY)) {
368 358 /* update rx hash table for this ARP */
drivers/net/bonding/bond_main.c
... ... @@ -1444,8 +1444,8 @@
1444 1444 struct sk_buff *skb = *pskb;
1445 1445 struct slave *slave;
1446 1446 struct bonding *bond;
1447   - int (*recv_probe)(struct sk_buff *, struct bonding *,
1448   - struct slave *);
  1447 + int (*recv_probe)(const struct sk_buff *, struct bonding *,
  1448 + struct slave *);
1449 1449 int ret = RX_HANDLER_ANOTHER;
1450 1450  
1451 1451 skb = skb_share_check(skb, GFP_ATOMIC);
... ... @@ -1462,15 +1462,10 @@
1462 1462  
1463 1463 recv_probe = ACCESS_ONCE(bond->recv_probe);
1464 1464 if (recv_probe) {
1465   - struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
1466   -
1467   - if (likely(nskb)) {
1468   - ret = recv_probe(nskb, bond, slave);
1469   - dev_kfree_skb(nskb);
1470   - if (ret == RX_HANDLER_CONSUMED) {
1471   - consume_skb(skb);
1472   - return ret;
1473   - }
  1465 + ret = recv_probe(skb, bond, slave);
  1466 + if (ret == RX_HANDLER_CONSUMED) {
  1467 + consume_skb(skb);
  1468 + return ret;
1474 1469 }
1475 1470 }
1476 1471  
1477 1472  
1478 1473  
1479 1474  
1480 1475  
1481 1476  
... ... @@ -2737,25 +2732,31 @@
2737 2732 }
2738 2733 }
2739 2734  
2740   -static int bond_arp_rcv(struct sk_buff *skb, struct bonding *bond,
2741   - struct slave *slave)
  2735 +static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
  2736 + struct slave *slave)
2742 2737 {
2743   - struct arphdr *arp;
  2738 + struct arphdr *arp = (struct arphdr *)skb->data;
2744 2739 unsigned char *arp_ptr;
2745 2740 __be32 sip, tip;
  2741 + int alen;
2746 2742  
2747 2743 if (skb->protocol != __cpu_to_be16(ETH_P_ARP))
2748 2744 return RX_HANDLER_ANOTHER;
2749 2745  
2750 2746 read_lock(&bond->lock);
  2747 + alen = arp_hdr_len(bond->dev);
2751 2748  
2752 2749 pr_debug("bond_arp_rcv: bond %s skb->dev %s\n",
2753 2750 bond->dev->name, skb->dev->name);
2754 2751  
2755   - if (!pskb_may_pull(skb, arp_hdr_len(bond->dev)))
2756   - goto out_unlock;
  2752 + if (alen > skb_headlen(skb)) {
  2753 + arp = kmalloc(alen, GFP_ATOMIC);
  2754 + if (!arp)
  2755 + goto out_unlock;
  2756 + if (skb_copy_bits(skb, 0, arp, alen) < 0)
  2757 + goto out_unlock;
  2758 + }
2757 2759  
2758   - arp = arp_hdr(skb);
2759 2760 if (arp->ar_hln != bond->dev->addr_len ||
2760 2761 skb->pkt_type == PACKET_OTHERHOST ||
2761 2762 skb->pkt_type == PACKET_LOOPBACK ||
... ... @@ -2790,6 +2791,8 @@
2790 2791  
2791 2792 out_unlock:
2792 2793 read_unlock(&bond->lock);
  2794 + if (arp != (struct arphdr *)skb->data)
  2795 + kfree(arp);
2793 2796 return RX_HANDLER_ANOTHER;
2794 2797 }
2795 2798  
drivers/net/bonding/bonding.h
... ... @@ -218,8 +218,8 @@
218 218 struct slave *primary_slave;
219 219 bool force_primary;
220 220 s32 slave_cnt; /* never change this value outside the attach/detach wrappers */
221   - int (*recv_probe)(struct sk_buff *, struct bonding *,
222   - struct slave *);
  221 + int (*recv_probe)(const struct sk_buff *, struct bonding *,
  222 + struct slave *);
223 223 rwlock_t lock;
224 224 rwlock_t curr_slave_lock;
225 225 u8 send_peer_notif;