Commit de063b7040dcd9fbc9a1847fa44f0af13e19d6de
Committed by
David S. Miller
1 parent
072c0559e2
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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; |