Skip to content

Commit e415ed3

Browse files
vaverindavem330
authored andcommitted
ipv6: use skb_expand_head in ip6_finish_output2
Unlike skb_realloc_headroom, new helper skb_expand_head does not allocate a new skb if possible. Additionally this patch replaces commonly used dereferencing with variables. Signed-off-by: Vasily Averin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f1260ff commit e415ed3

File tree

1 file changed

+16
-35
lines changed

1 file changed

+16
-35
lines changed

net/ipv6/ip6_output.c

+16-35
Original file line numberDiff line numberDiff line change
@@ -60,46 +60,29 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
6060
{
6161
struct dst_entry *dst = skb_dst(skb);
6262
struct net_device *dev = dst->dev;
63+
struct inet6_dev *idev = ip6_dst_idev(dst);
6364
unsigned int hh_len = LL_RESERVED_SPACE(dev);
64-
int delta = hh_len - skb_headroom(skb);
65-
const struct in6_addr *nexthop;
65+
const struct in6_addr *daddr, *nexthop;
66+
struct ipv6hdr *hdr;
6667
struct neighbour *neigh;
6768
int ret;
6869

6970
/* Be paranoid, rather than too clever. */
70-
if (unlikely(delta > 0) && dev->header_ops) {
71-
/* pskb_expand_head() might crash, if skb is shared */
72-
if (skb_shared(skb)) {
73-
struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
74-
75-
if (likely(nskb)) {
76-
if (skb->sk)
77-
skb_set_owner_w(nskb, skb->sk);
78-
consume_skb(skb);
79-
} else {
80-
kfree_skb(skb);
81-
}
82-
skb = nskb;
83-
}
84-
if (skb &&
85-
pskb_expand_head(skb, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
86-
kfree_skb(skb);
87-
skb = NULL;
88-
}
71+
if (unlikely(hh_len > skb_headroom(skb)) && dev->header_ops) {
72+
skb = skb_expand_head(skb, hh_len);
8973
if (!skb) {
90-
IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS);
74+
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
9175
return -ENOMEM;
9276
}
9377
}
9478

95-
if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr)) {
96-
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
97-
79+
hdr = ipv6_hdr(skb);
80+
daddr = &hdr->daddr;
81+
if (ipv6_addr_is_multicast(daddr)) {
9882
if (!(dev->flags & IFF_LOOPBACK) && sk_mc_loop(sk) &&
9983
((mroute6_is_socket(net, skb) &&
10084
!(IP6CB(skb)->flags & IP6SKB_FORWARDED)) ||
101-
ipv6_chk_mcast_addr(dev, &ipv6_hdr(skb)->daddr,
102-
&ipv6_hdr(skb)->saddr))) {
85+
ipv6_chk_mcast_addr(dev, daddr, &hdr->saddr))) {
10386
struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);
10487

10588
/* Do not check for IFF_ALLMULTI; multicast routing
@@ -110,7 +93,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
11093
net, sk, newskb, NULL, newskb->dev,
11194
dev_loopback_xmit);
11295

113-
if (ipv6_hdr(skb)->hop_limit == 0) {
96+
if (hdr->hop_limit == 0) {
11497
IP6_INC_STATS(net, idev,
11598
IPSTATS_MIB_OUTDISCARDS);
11699
kfree_skb(skb);
@@ -119,9 +102,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
119102
}
120103

121104
IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, skb->len);
122-
123-
if (IPV6_ADDR_MC_SCOPE(&ipv6_hdr(skb)->daddr) <=
124-
IPV6_ADDR_SCOPE_NODELOCAL &&
105+
if (IPV6_ADDR_MC_SCOPE(daddr) <= IPV6_ADDR_SCOPE_NODELOCAL &&
125106
!(dev->flags & IFF_LOOPBACK)) {
126107
kfree_skb(skb);
127108
return 0;
@@ -136,10 +117,10 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
136117
}
137118

138119
rcu_read_lock_bh();
139-
nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
140-
neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
120+
nexthop = rt6_nexthop((struct rt6_info *)dst, daddr);
121+
neigh = __ipv6_neigh_lookup_noref(dev, nexthop);
141122
if (unlikely(!neigh))
142-
neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
123+
neigh = __neigh_create(&nd_tbl, nexthop, dev, false);
143124
if (!IS_ERR(neigh)) {
144125
sock_confirm_neigh(skb, neigh);
145126
ret = neigh_output(neigh, skb, false);
@@ -148,7 +129,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
148129
}
149130
rcu_read_unlock_bh();
150131

151-
IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
132+
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES);
152133
kfree_skb(skb);
153134
return -EINVAL;
154135
}

0 commit comments

Comments
 (0)