Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81d626b0 authored by Vasily Averin's avatar Vasily Averin Committed by Greg Kroah-Hartman
Browse files

ipv6: use skb_expand_head in ip6_xmit



[ Upstream commit 0c9f227bee11910a49e1d159abe102d06e3745d5 ]

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: default avatarVasily Averin <vvs@virtuozzo.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
(cherry picked from commit 0c9f227bee11910a49e1d159abe102d06e3745d5)
Signed-off-by: default avatarHarshvardhan Jha <harshvardhan.j.jha@oracle.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 1598154f
Loading
Loading
Loading
Loading
+11 −16
Original line number Diff line number Diff line
@@ -253,6 +253,8 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
	const struct ipv6_pinfo *np = inet6_sk(sk);
	struct in6_addr *first_hop = &fl6->daddr;
	struct dst_entry *dst = skb_dst(skb);
	struct net_device *dev = dst->dev;
	struct inet6_dev *idev = ip6_dst_idev(dst);
	unsigned int head_room;
	struct ipv6hdr *hdr;
	u8  proto = fl6->flowi6_proto;
@@ -260,22 +262,16 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
	int hlimit = -1;
	u32 mtu;

	head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dst->dev);
	head_room = sizeof(struct ipv6hdr) + LL_RESERVED_SPACE(dev);
	if (opt)
		head_room += opt->opt_nflen + opt->opt_flen;

	if (unlikely(skb_headroom(skb) < head_room)) {
		struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room);
		if (!skb2) {
			IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
				      IPSTATS_MIB_OUTDISCARDS);
			kfree_skb(skb);
	if (unlikely(head_room > skb_headroom(skb))) {
		skb = skb_expand_head(skb, head_room);
		if (!skb) {
			IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
			return -ENOBUFS;
		}
		if (skb->sk)
			skb_set_owner_w(skb2, skb->sk);
		consume_skb(skb);
		skb = skb2;
	}

	if (opt) {
@@ -317,8 +313,7 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,

	mtu = dst_mtu(dst);
	if ((skb->len <= mtu) || skb->ignore_df || skb_is_gso(skb)) {
		IP6_UPD_PO_STATS(net, ip6_dst_idev(skb_dst(skb)),
			      IPSTATS_MIB_OUT, skb->len);
		IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

		/* if egress device is enslaved to an L3 master device pass the
		 * skb to its handler for processing
@@ -331,17 +326,17 @@ int ip6_xmit(const struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
		 * we promote our socket to non const
		 */
		return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
			       net, (struct sock *)sk, skb, NULL, dst->dev,
			       net, (struct sock *)sk, skb, NULL, dev,
			       dst_output);
	}

	skb->dev = dst->dev;
	skb->dev = dev;
	/* ipv6_local_error() does not require socket lock,
	 * we promote our socket to non const
	 */
	ipv6_local_error((struct sock *)sk, EMSGSIZE, fl6, mtu);

	IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_FRAGFAILS);
	IP6_INC_STATS(net, idev, IPSTATS_MIB_FRAGFAILS);
	kfree_skb(skb);
	return -EMSGSIZE;
}