aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/devinet.c
diff options
context:
space:
mode:
authorMadhu Challa <challa@noironetworks.com>2015-02-25 12:58:35 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-27 16:25:25 -0500
commit93a714d6b53d87872e552dbb273544bdeaaf6e12 (patch)
tree3cc79521cb6dbcd600384507329ecef93ae618ab /net/ipv4/devinet.c
parent46a4dee074b58c4256dbf6c2dbf199c372f85b04 (diff)
multicast: Extend ip address command to enable multicast group join/leave on
Joining multicast group on ethernet level via "ip maddr" command would not work if we have an Ethernet switch that does igmp snooping since the switch would not replicate multicast packets on ports that did not have IGMP reports for the multicast addresses. Linux vxlan interfaces created via "ip link add vxlan" have the group option that enables then to do the required join. By extending ip address command with option "autojoin" we can get similar functionality for openvswitch vxlan interfaces as well as other tunneling mechanisms that need to receive multicast traffic. The kernel code is structured similar to how the vxlan driver does a group join / leave. example: ip address add 224.1.1.10/24 dev eth5 autojoin ip address del 224.1.1.10/24 dev eth5 Signed-off-by: Madhu Challa <challa@noironetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r--net/ipv4/devinet.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 3a8985c94581..5105759e4e00 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -548,6 +548,26 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix,
548 return NULL; 548 return NULL;
549} 549}
550 550
551static int ip_mc_config(struct sock *sk, bool join, const struct in_ifaddr *ifa)
552{
553 struct ip_mreqn mreq = {
554 .imr_multiaddr.s_addr = ifa->ifa_address,
555 .imr_ifindex = ifa->ifa_dev->dev->ifindex,
556 };
557 int ret;
558
559 ASSERT_RTNL();
560
561 lock_sock(sk);
562 if (join)
563 ret = __ip_mc_join_group(sk, &mreq);
564 else
565 ret = __ip_mc_leave_group(sk, &mreq);
566 release_sock(sk);
567
568 return ret;
569}
570
551static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh) 571static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
552{ 572{
553 struct net *net = sock_net(skb->sk); 573 struct net *net = sock_net(skb->sk);
@@ -584,6 +604,8 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
584 !inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa))) 604 !inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa)))
585 continue; 605 continue;
586 606
607 if (ipv4_is_multicast(ifa->ifa_address))
608 ip_mc_config(net->ipv4.mc_autojoin_sk, false, ifa);
587 __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid); 609 __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid);
588 return 0; 610 return 0;
589 } 611 }
@@ -838,6 +860,15 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
838 * userspace already relies on not having to provide this. 860 * userspace already relies on not having to provide this.
839 */ 861 */
840 set_ifa_lifetime(ifa, valid_lft, prefered_lft); 862 set_ifa_lifetime(ifa, valid_lft, prefered_lft);
863 if (ifa->ifa_flags & IFA_F_MCAUTOJOIN) {
864 int ret = ip_mc_config(net->ipv4.mc_autojoin_sk,
865 true, ifa);
866
867 if (ret < 0) {
868 inet_free_ifa(ifa);
869 return ret;
870 }
871 }
841 return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid); 872 return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid);
842 } else { 873 } else {
843 inet_free_ifa(ifa); 874 inet_free_ifa(ifa);