[IPV6] MCAST: Use standard path for sending MLD/MLDv2 messages.
This is changing the paths for sending MLD/MLDv2 messages from dev_queue_xmit() to standard dst_output(). Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
This commit is contained in:
@@ -1433,25 +1433,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
|
|||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
struct net_device *dev = skb->dev;
|
|
||||||
unsigned char ha[MAX_ADDR_LEN];
|
|
||||||
|
|
||||||
ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1);
|
|
||||||
if (dev_hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len) < 0) {
|
|
||||||
kfree_skb(skb);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return dev_queue_xmit(skb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int mld_dev_queue_xmit(struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
return NF_HOOK(PF_INET6, NF_INET_POST_ROUTING, skb, NULL, skb->dev,
|
|
||||||
mld_dev_queue_xmit2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mld_sendpack(struct sk_buff *skb)
|
static void mld_sendpack(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ipv6hdr *pip6 = ipv6_hdr(skb);
|
struct ipv6hdr *pip6 = ipv6_hdr(skb);
|
||||||
@@ -1460,6 +1441,7 @@ static void mld_sendpack(struct sk_buff *skb)
|
|||||||
int payload_len, mldlen;
|
int payload_len, mldlen;
|
||||||
struct inet6_dev *idev = in6_dev_get(skb->dev);
|
struct inet6_dev *idev = in6_dev_get(skb->dev);
|
||||||
int err;
|
int err;
|
||||||
|
struct flowi fl;
|
||||||
|
|
||||||
IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
|
IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
|
||||||
payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
|
payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
|
||||||
@@ -1469,8 +1451,25 @@ static void mld_sendpack(struct sk_buff *skb)
|
|||||||
pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
|
pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
|
||||||
IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb),
|
IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb),
|
||||||
mldlen, 0));
|
mldlen, 0));
|
||||||
|
|
||||||
|
skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
|
||||||
|
|
||||||
|
if (!skb->dst) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
icmpv6_flow_init(igmp6_socket->sk, &fl, ICMPV6_MLD2_REPORT,
|
||||||
|
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
|
||||||
|
skb->dev->ifindex);
|
||||||
|
|
||||||
|
err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
|
err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
|
||||||
mld_dev_queue_xmit);
|
dst_output);
|
||||||
|
out:
|
||||||
if (!err) {
|
if (!err) {
|
||||||
ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
|
ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
|
||||||
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
|
ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
|
||||||
@@ -1480,6 +1479,11 @@ static void mld_sendpack(struct sk_buff *skb)
|
|||||||
|
|
||||||
if (likely(idev != NULL))
|
if (likely(idev != NULL))
|
||||||
in6_dev_put(idev);
|
in6_dev_put(idev);
|
||||||
|
return;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
kfree_skb(skb);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
|
static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
|
||||||
@@ -1761,6 +1765,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
|
|||||||
u8 ra[8] = { IPPROTO_ICMPV6, 0,
|
u8 ra[8] = { IPPROTO_ICMPV6, 0,
|
||||||
IPV6_TLV_ROUTERALERT, 2, 0, 0,
|
IPV6_TLV_ROUTERALERT, 2, 0, 0,
|
||||||
IPV6_TLV_PADN, 0 };
|
IPV6_TLV_PADN, 0 };
|
||||||
|
struct flowi fl;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
IP6_INC_STATS(__in6_dev_get(dev),
|
IP6_INC_STATS(__in6_dev_get(dev),
|
||||||
@@ -1813,8 +1818,23 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
|
|||||||
|
|
||||||
idev = in6_dev_get(skb->dev);
|
idev = in6_dev_get(skb->dev);
|
||||||
|
|
||||||
|
skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
|
||||||
|
if (!skb->dst) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
icmpv6_flow_init(igmp6_socket->sk, &fl, type,
|
||||||
|
&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
|
||||||
|
skb->dev->ifindex);
|
||||||
|
|
||||||
|
err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
|
err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
|
||||||
mld_dev_queue_xmit);
|
dst_output);
|
||||||
|
out:
|
||||||
if (!err) {
|
if (!err) {
|
||||||
ICMP6MSGOUT_INC_STATS(idev, type);
|
ICMP6MSGOUT_INC_STATS(idev, type);
|
||||||
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
|
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
|
||||||
@@ -1825,6 +1845,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
|
|||||||
if (likely(idev != NULL))
|
if (likely(idev != NULL))
|
||||||
in6_dev_put(idev);
|
in6_dev_put(idev);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
kfree_skb(skb);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
|
static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
|
||||||
|
Reference in New Issue
Block a user