static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
{
	u8 ra[8] = { IPPROTO_ICMPV6, 0, IPV6_TLV_ROUTERALERT,
		     2, 0, 0, IPV6_TLV_PADN, 0 };
	struct net_device *dev = idev->dev;
	int hlen = LL_RESERVED_SPACE(dev);
	int tlen = dev->needed_tailroom;
	struct net *net = dev_net(dev);
	const struct in6_addr *saddr;
	struct in6_addr addr_buf;
	struct mld2_report *pmr;
	struct sk_buff *skb;
	unsigned int size;
	struct sock *sk;
	int err;

	sk = net->ipv6.igmp_sk;
	/* we assume size > sizeof(ra) here
	 * Also try to not allocate high-order pages for big MTU
	 */
	size = min_t(int, mtu, PAGE_SIZE / 2) + hlen + tlen;
	skb = sock_alloc_send_skb(sk, size, 1, &err);
	if (!skb)
		return NULL;

	skb->priority = TC_PRIO_CONTROL;
	skb_reserve(skb, hlen);
	skb_tailroom_reserve(skb, mtu, tlen);

	if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
		/* <draft-ietf-magma-mld-source-05.txt>:
		 * use unspecified address as the source address
		 * when a valid link-local address is not available.
		 */
		saddr = &in6addr_any;
	} else
		saddr = &addr_buf;

	ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);

	skb_put_data(skb, ra, sizeof(ra));

	skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);
	skb_put(skb, sizeof(*pmr));
	pmr = (struct mld2_report *)skb_transport_header(skb);
	pmr->mld2r_type = ICMPV6_MLD2_REPORT;
	pmr->mld2r_resv1 = 0;
	pmr->mld2r_cksum = 0;
	pmr->mld2r_resv2 = 0;
	pmr->mld2r_ngrec = 0;
	return skb;
}
static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
{
	u8 ra[8] = { IPPROTO_ICMPV6, 0, IPV6_TLV_ROUTERALERT,
		     2, 0, 0, IPV6_TLV_PADN, 0 };
	struct net_device *dev = idev->dev;
	int hlen = LL_RESERVED_SPACE(dev);
	int tlen = dev->needed_tailroom;
	struct net *net = dev_net(dev);
	const struct in6_addr *saddr;
	struct in6_addr addr_buf;
	struct mld2_report *pmr;
	struct sk_buff *skb;
	unsigned int size;
	struct sock *sk;
	int err;

	sk = net->ipv6.igmp_sk;
	 
	size = min_t(int, mtu, PAGE_SIZE / 2) + hlen + tlen;
	skb = sock_alloc_send_skb(sk, size, 1, &err);
	if (!skb)
		return NULL;

	skb->priority = TC_PRIO_CONTROL;
	skb_reserve(skb, hlen);
	skb_tailroom_reserve(skb, mtu, tlen);

	if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
		 
		saddr = &in6addr_any;
	} else
		saddr = &addr_buf;

	ip6_mc_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);

	skb_put_data(skb, ra, sizeof(ra));

	skb_set_transport_header(skb, skb_tail_pointer(skb) - skb->data);
	skb_put(skb, sizeof(*pmr));
	pmr = (struct mld2_report *)skb_transport_header(skb);
	pmr->mld2r_type = ICMPV6_MLD2_REPORT;
	pmr->mld2r_resv1 = 0;
	pmr->mld2r_cksum = 0;
	pmr->mld2r_resv2 = 0;
	pmr->mld2r_ngrec = 0;
	return skb;
}