aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2013-01-21 01:00:26 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-21 13:55:14 -0500
commit660b26dc1a8aeb33c2a2246ebf1b3684449a74b7 (patch)
tree867f1141b7cc2396443b7fa293124a8ef0948330 /net
parentbbb923a4c2d17ebd5ec34755fe19a33914cbd86f (diff)
mcast: add multicast proxy support (IPv4 and IPv6)
This patch add the support of proxy multicast, ie being able to build a static multicast tree. It adds the support of (*,*) and (*,G) entries. The user should define an (*,*) entry which is not used for real forwarding. This entry defines the upstream in iif and contains all interfaces from the static tree in its oifs. It will be used to forward packet upstream when they come from an interface belonging to the static tree. Hence, the user should define (*,G) entries to build its static tree. Note that upstream interface must be part of oifs: packets are sent to all oifs interfaces except the input interface. This ensures to always join the whole static tree, even if the packet is not coming from the upstream interface. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Acked-by: David L Stevens <dlstevens@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ipmr.c119
-rw-r--r--net/ipv6/ip6mr.c126
2 files changed, 219 insertions, 26 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index a9454cbd953c..4b5e22670d44 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -828,6 +828,49 @@ static struct mfc_cache *ipmr_cache_find(struct mr_table *mrt,
828 return NULL; 828 return NULL;
829} 829}
830 830
831/* Look for a (*,*,oif) entry */
832static struct mfc_cache *ipmr_cache_find_any_parent(struct mr_table *mrt,
833 int vifi)
834{
835 int line = MFC_HASH(INADDR_ANY, INADDR_ANY);
836 struct mfc_cache *c;
837
838 list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
839 if (c->mfc_origin == INADDR_ANY &&
840 c->mfc_mcastgrp == INADDR_ANY &&
841 c->mfc_un.res.ttls[vifi] < 255)
842 return c;
843
844 return NULL;
845}
846
847/* Look for a (*,G) entry */
848static struct mfc_cache *ipmr_cache_find_any(struct mr_table *mrt,
849 __be32 mcastgrp, int vifi)
850{
851 int line = MFC_HASH(mcastgrp, INADDR_ANY);
852 struct mfc_cache *c, *proxy;
853
854 if (mcastgrp == INADDR_ANY)
855 goto skip;
856
857 list_for_each_entry_rcu(c, &mrt->mfc_cache_array[line], list)
858 if (c->mfc_origin == INADDR_ANY &&
859 c->mfc_mcastgrp == mcastgrp) {
860 if (c->mfc_un.res.ttls[vifi] < 255)
861 return c;
862
863 /* It's ok if the vifi is part of the static tree */
864 proxy = ipmr_cache_find_any_parent(mrt,
865 c->mfc_parent);
866 if (proxy && proxy->mfc_un.res.ttls[vifi] < 255)
867 return c;
868 }
869
870skip:
871 return ipmr_cache_find_any_parent(mrt, vifi);
872}
873
831/* 874/*
832 * Allocate a multicast cache entry 875 * Allocate a multicast cache entry
833 */ 876 */
@@ -1053,7 +1096,7 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb)
1053 * MFC cache manipulation by user space mroute daemon 1096 * MFC cache manipulation by user space mroute daemon
1054 */ 1097 */
1055 1098
1056static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc) 1099static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc, int parent)
1057{ 1100{
1058 int line; 1101 int line;
1059 struct mfc_cache *c, *next; 1102 struct mfc_cache *c, *next;
@@ -1062,7 +1105,8 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
1062 1105
1063 list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) { 1106 list_for_each_entry_safe(c, next, &mrt->mfc_cache_array[line], list) {
1064 if (c->mfc_origin == mfc->mfcc_origin.s_addr && 1107 if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
1065 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { 1108 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr &&
1109 (parent == -1 || parent == c->mfc_parent)) {
1066 list_del_rcu(&c->list); 1110 list_del_rcu(&c->list);
1067 mroute_netlink_event(mrt, c, RTM_DELROUTE); 1111 mroute_netlink_event(mrt, c, RTM_DELROUTE);
1068 ipmr_cache_free(c); 1112 ipmr_cache_free(c);
@@ -1073,7 +1117,7 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
1073} 1117}
1074 1118
1075static int ipmr_mfc_add(struct net *net, struct mr_table *mrt, 1119static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1076 struct mfcctl *mfc, int mrtsock) 1120 struct mfcctl *mfc, int mrtsock, int parent)
1077{ 1121{
1078 bool found = false; 1122 bool found = false;
1079 int line; 1123 int line;
@@ -1086,7 +1130,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1086 1130
1087 list_for_each_entry(c, &mrt->mfc_cache_array[line], list) { 1131 list_for_each_entry(c, &mrt->mfc_cache_array[line], list) {
1088 if (c->mfc_origin == mfc->mfcc_origin.s_addr && 1132 if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
1089 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) { 1133 c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr &&
1134 (parent == -1 || parent == c->mfc_parent)) {
1090 found = true; 1135 found = true;
1091 break; 1136 break;
1092 } 1137 }
@@ -1103,7 +1148,8 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
1103 return 0; 1148 return 0;
1104 } 1149 }
1105 1150
1106 if (!ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr)) 1151 if (mfc->mfcc_mcastgrp.s_addr != INADDR_ANY &&
1152 !ipv4_is_multicast(mfc->mfcc_mcastgrp.s_addr))
1107 return -EINVAL; 1153 return -EINVAL;
1108 1154
1109 c = ipmr_cache_alloc(); 1155 c = ipmr_cache_alloc();
@@ -1218,7 +1264,7 @@ static void mrtsock_destruct(struct sock *sk)
1218 1264
1219int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen) 1265int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
1220{ 1266{
1221 int ret; 1267 int ret, parent = 0;
1222 struct vifctl vif; 1268 struct vifctl vif;
1223 struct mfcctl mfc; 1269 struct mfcctl mfc;
1224 struct net *net = sock_net(sk); 1270 struct net *net = sock_net(sk);
@@ -1287,16 +1333,22 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1287 */ 1333 */
1288 case MRT_ADD_MFC: 1334 case MRT_ADD_MFC:
1289 case MRT_DEL_MFC: 1335 case MRT_DEL_MFC:
1336 parent = -1;
1337 case MRT_ADD_MFC_PROXY:
1338 case MRT_DEL_MFC_PROXY:
1290 if (optlen != sizeof(mfc)) 1339 if (optlen != sizeof(mfc))
1291 return -EINVAL; 1340 return -EINVAL;
1292 if (copy_from_user(&mfc, optval, sizeof(mfc))) 1341 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1293 return -EFAULT; 1342 return -EFAULT;
1343 if (parent == 0)
1344 parent = mfc.mfcc_parent;
1294 rtnl_lock(); 1345 rtnl_lock();
1295 if (optname == MRT_DEL_MFC) 1346 if (optname == MRT_DEL_MFC || optname == MRT_DEL_MFC_PROXY)
1296 ret = ipmr_mfc_delete(mrt, &mfc); 1347 ret = ipmr_mfc_delete(mrt, &mfc, parent);
1297 else 1348 else
1298 ret = ipmr_mfc_add(net, mrt, &mfc, 1349 ret = ipmr_mfc_add(net, mrt, &mfc,
1299 sk == rtnl_dereference(mrt->mroute_sk)); 1350 sk == rtnl_dereference(mrt->mroute_sk),
1351 parent);
1300 rtnl_unlock(); 1352 rtnl_unlock();
1301 return ret; 1353 return ret;
1302 /* 1354 /*
@@ -1749,17 +1801,28 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1749{ 1801{
1750 int psend = -1; 1802 int psend = -1;
1751 int vif, ct; 1803 int vif, ct;
1804 int true_vifi = ipmr_find_vif(mrt, skb->dev);
1752 1805
1753 vif = cache->mfc_parent; 1806 vif = cache->mfc_parent;
1754 cache->mfc_un.res.pkt++; 1807 cache->mfc_un.res.pkt++;
1755 cache->mfc_un.res.bytes += skb->len; 1808 cache->mfc_un.res.bytes += skb->len;
1756 1809
1810 if (cache->mfc_origin == INADDR_ANY && true_vifi >= 0) {
1811 struct mfc_cache *cache_proxy;
1812
1813 /* For an (*,G) entry, we only check that the incomming
1814 * interface is part of the static tree.
1815 */
1816 cache_proxy = ipmr_cache_find_any_parent(mrt, vif);
1817 if (cache_proxy &&
1818 cache_proxy->mfc_un.res.ttls[true_vifi] < 255)
1819 goto forward;
1820 }
1821
1757 /* 1822 /*
1758 * Wrong interface: drop packet and (maybe) send PIM assert. 1823 * Wrong interface: drop packet and (maybe) send PIM assert.
1759 */ 1824 */
1760 if (mrt->vif_table[vif].dev != skb->dev) { 1825 if (mrt->vif_table[vif].dev != skb->dev) {
1761 int true_vifi;
1762
1763 if (rt_is_output_route(skb_rtable(skb))) { 1826 if (rt_is_output_route(skb_rtable(skb))) {
1764 /* It is our own packet, looped back. 1827 /* It is our own packet, looped back.
1765 * Very complicated situation... 1828 * Very complicated situation...
@@ -1776,7 +1839,6 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1776 } 1839 }
1777 1840
1778 cache->mfc_un.res.wrong_if++; 1841 cache->mfc_un.res.wrong_if++;
1779 true_vifi = ipmr_find_vif(mrt, skb->dev);
1780 1842
1781 if (true_vifi >= 0 && mrt->mroute_do_assert && 1843 if (true_vifi >= 0 && mrt->mroute_do_assert &&
1782 /* pimsm uses asserts, when switching from RPT to SPT, 1844 /* pimsm uses asserts, when switching from RPT to SPT,
@@ -1794,15 +1856,33 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1794 goto dont_forward; 1856 goto dont_forward;
1795 } 1857 }
1796 1858
1859forward:
1797 mrt->vif_table[vif].pkt_in++; 1860 mrt->vif_table[vif].pkt_in++;
1798 mrt->vif_table[vif].bytes_in += skb->len; 1861 mrt->vif_table[vif].bytes_in += skb->len;
1799 1862
1800 /* 1863 /*
1801 * Forward the frame 1864 * Forward the frame
1802 */ 1865 */
1866 if (cache->mfc_origin == INADDR_ANY &&
1867 cache->mfc_mcastgrp == INADDR_ANY) {
1868 if (true_vifi >= 0 &&
1869 true_vifi != cache->mfc_parent &&
1870 ip_hdr(skb)->ttl >
1871 cache->mfc_un.res.ttls[cache->mfc_parent]) {
1872 /* It's an (*,*) entry and the packet is not coming from
1873 * the upstream: forward the packet to the upstream
1874 * only.
1875 */
1876 psend = cache->mfc_parent;
1877 goto last_forward;
1878 }
1879 goto dont_forward;
1880 }
1803 for (ct = cache->mfc_un.res.maxvif - 1; 1881 for (ct = cache->mfc_un.res.maxvif - 1;
1804 ct >= cache->mfc_un.res.minvif; ct--) { 1882 ct >= cache->mfc_un.res.minvif; ct--) {
1805 if (ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) { 1883 /* For (*,G) entry, don't forward to the incoming interface */
1884 if ((cache->mfc_origin != INADDR_ANY || ct != true_vifi) &&
1885 ip_hdr(skb)->ttl > cache->mfc_un.res.ttls[ct]) {
1806 if (psend != -1) { 1886 if (psend != -1) {
1807 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1887 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
1808 1888
@@ -1813,6 +1893,7 @@ static int ip_mr_forward(struct net *net, struct mr_table *mrt,
1813 psend = ct; 1893 psend = ct;
1814 } 1894 }
1815 } 1895 }
1896last_forward:
1816 if (psend != -1) { 1897 if (psend != -1) {
1817 if (local) { 1898 if (local) {
1818 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 1899 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
@@ -1902,6 +1983,13 @@ int ip_mr_input(struct sk_buff *skb)
1902 1983
1903 /* already under rcu_read_lock() */ 1984 /* already under rcu_read_lock() */
1904 cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr); 1985 cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
1986 if (cache == NULL) {
1987 int vif = ipmr_find_vif(mrt, skb->dev);
1988
1989 if (vif >= 0)
1990 cache = ipmr_cache_find_any(mrt, ip_hdr(skb)->daddr,
1991 vif);
1992 }
1905 1993
1906 /* 1994 /*
1907 * No usable cache entry 1995 * No usable cache entry
@@ -2107,7 +2195,12 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
2107 2195
2108 rcu_read_lock(); 2196 rcu_read_lock();
2109 cache = ipmr_cache_find(mrt, saddr, daddr); 2197 cache = ipmr_cache_find(mrt, saddr, daddr);
2198 if (cache == NULL && skb->dev) {
2199 int vif = ipmr_find_vif(mrt, skb->dev);
2110 2200
2201 if (vif >= 0)
2202 cache = ipmr_cache_find_any(mrt, daddr, vif);
2203 }
2111 if (cache == NULL) { 2204 if (cache == NULL) {
2112 struct sk_buff *skb2; 2205 struct sk_buff *skb2;
2113 struct iphdr *iph; 2206 struct iphdr *iph;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 26dcdec9e3a5..acc32494006a 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1017,6 +1017,50 @@ static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt,
1017 return NULL; 1017 return NULL;
1018} 1018}
1019 1019
1020/* Look for a (*,*,oif) entry */
1021static struct mfc6_cache *ip6mr_cache_find_any_parent(struct mr6_table *mrt,
1022 mifi_t mifi)
1023{
1024 int line = MFC6_HASH(&in6addr_any, &in6addr_any);
1025 struct mfc6_cache *c;
1026
1027 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list)
1028 if (ipv6_addr_any(&c->mf6c_origin) &&
1029 ipv6_addr_any(&c->mf6c_mcastgrp) &&
1030 (c->mfc_un.res.ttls[mifi] < 255))
1031 return c;
1032
1033 return NULL;
1034}
1035
1036/* Look for a (*,G) entry */
1037static struct mfc6_cache *ip6mr_cache_find_any(struct mr6_table *mrt,
1038 struct in6_addr *mcastgrp,
1039 mifi_t mifi)
1040{
1041 int line = MFC6_HASH(mcastgrp, &in6addr_any);
1042 struct mfc6_cache *c, *proxy;
1043
1044 if (ipv6_addr_any(mcastgrp))
1045 goto skip;
1046
1047 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list)
1048 if (ipv6_addr_any(&c->mf6c_origin) &&
1049 ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp)) {
1050 if (c->mfc_un.res.ttls[mifi] < 255)
1051 return c;
1052
1053 /* It's ok if the mifi is part of the static tree */
1054 proxy = ip6mr_cache_find_any_parent(mrt,
1055 c->mf6c_parent);
1056 if (proxy && proxy->mfc_un.res.ttls[mifi] < 255)
1057 return c;
1058 }
1059
1060skip:
1061 return ip6mr_cache_find_any_parent(mrt, mifi);
1062}
1063
1020/* 1064/*
1021 * Allocate a multicast cache entry 1065 * Allocate a multicast cache entry
1022 */ 1066 */
@@ -1247,7 +1291,8 @@ ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
1247 * MFC6 cache manipulation by user space 1291 * MFC6 cache manipulation by user space
1248 */ 1292 */
1249 1293
1250static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc) 1294static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc,
1295 int parent)
1251{ 1296{
1252 int line; 1297 int line;
1253 struct mfc6_cache *c, *next; 1298 struct mfc6_cache *c, *next;
@@ -1256,7 +1301,9 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc)
1256 1301
1257 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) { 1302 list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) {
1258 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && 1303 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
1259 ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { 1304 ipv6_addr_equal(&c->mf6c_mcastgrp,
1305 &mfc->mf6cc_mcastgrp.sin6_addr) &&
1306 (parent == -1 || parent == c->mf6c_parent)) {
1260 write_lock_bh(&mrt_lock); 1307 write_lock_bh(&mrt_lock);
1261 list_del(&c->list); 1308 list_del(&c->list);
1262 write_unlock_bh(&mrt_lock); 1309 write_unlock_bh(&mrt_lock);
@@ -1391,7 +1438,7 @@ void ip6_mr_cleanup(void)
1391} 1438}
1392 1439
1393static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt, 1440static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1394 struct mf6cctl *mfc, int mrtsock) 1441 struct mf6cctl *mfc, int mrtsock, int parent)
1395{ 1442{
1396 bool found = false; 1443 bool found = false;
1397 int line; 1444 int line;
@@ -1413,7 +1460,9 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1413 1460
1414 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { 1461 list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) {
1415 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) && 1462 if (ipv6_addr_equal(&c->mf6c_origin, &mfc->mf6cc_origin.sin6_addr) &&
1416 ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) { 1463 ipv6_addr_equal(&c->mf6c_mcastgrp,
1464 &mfc->mf6cc_mcastgrp.sin6_addr) &&
1465 (parent == -1 || parent == mfc->mf6cc_parent)) {
1417 found = true; 1466 found = true;
1418 break; 1467 break;
1419 } 1468 }
@@ -1430,7 +1479,8 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
1430 return 0; 1479 return 0;
1431 } 1480 }
1432 1481
1433 if (!ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr)) 1482 if (!ipv6_addr_any(&mfc->mf6cc_mcastgrp.sin6_addr) &&
1483 !ipv6_addr_is_multicast(&mfc->mf6cc_mcastgrp.sin6_addr))
1434 return -EINVAL; 1484 return -EINVAL;
1435 1485
1436 c = ip6mr_cache_alloc(); 1486 c = ip6mr_cache_alloc();
@@ -1596,7 +1646,7 @@ struct sock *mroute6_socket(struct net *net, struct sk_buff *skb)
1596 1646
1597int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen) 1647int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsigned int optlen)
1598{ 1648{
1599 int ret; 1649 int ret, parent = 0;
1600 struct mif6ctl vif; 1650 struct mif6ctl vif;
1601 struct mf6cctl mfc; 1651 struct mf6cctl mfc;
1602 mifi_t mifi; 1652 mifi_t mifi;
@@ -1653,15 +1703,21 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
1653 */ 1703 */
1654 case MRT6_ADD_MFC: 1704 case MRT6_ADD_MFC:
1655 case MRT6_DEL_MFC: 1705 case MRT6_DEL_MFC:
1706 parent = -1;
1707 case MRT6_ADD_MFC_PROXY:
1708 case MRT6_DEL_MFC_PROXY:
1656 if (optlen < sizeof(mfc)) 1709 if (optlen < sizeof(mfc))
1657 return -EINVAL; 1710 return -EINVAL;
1658 if (copy_from_user(&mfc, optval, sizeof(mfc))) 1711 if (copy_from_user(&mfc, optval, sizeof(mfc)))
1659 return -EFAULT; 1712 return -EFAULT;
1713 if (parent == 0)
1714 parent = mfc.mf6cc_parent;
1660 rtnl_lock(); 1715 rtnl_lock();
1661 if (optname == MRT6_DEL_MFC) 1716 if (optname == MRT6_DEL_MFC || optname == MRT6_DEL_MFC_PROXY)
1662 ret = ip6mr_mfc_delete(mrt, &mfc); 1717 ret = ip6mr_mfc_delete(mrt, &mfc, parent);
1663 else 1718 else
1664 ret = ip6mr_mfc_add(net, mrt, &mfc, sk == mrt->mroute6_sk); 1719 ret = ip6mr_mfc_add(net, mrt, &mfc,
1720 sk == mrt->mroute6_sk, parent);
1665 rtnl_unlock(); 1721 rtnl_unlock();
1666 return ret; 1722 return ret;
1667 1723
@@ -2015,19 +2071,29 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
2015{ 2071{
2016 int psend = -1; 2072 int psend = -1;
2017 int vif, ct; 2073 int vif, ct;
2074 int true_vifi = ip6mr_find_vif(mrt, skb->dev);
2018 2075
2019 vif = cache->mf6c_parent; 2076 vif = cache->mf6c_parent;
2020 cache->mfc_un.res.pkt++; 2077 cache->mfc_un.res.pkt++;
2021 cache->mfc_un.res.bytes += skb->len; 2078 cache->mfc_un.res.bytes += skb->len;
2022 2079
2080 if (ipv6_addr_any(&cache->mf6c_origin) && true_vifi >= 0) {
2081 struct mfc6_cache *cache_proxy;
2082
2083 /* For an (*,G) entry, we only check that the incomming
2084 * interface is part of the static tree.
2085 */
2086 cache_proxy = ip6mr_cache_find_any_parent(mrt, vif);
2087 if (cache_proxy &&
2088 cache_proxy->mfc_un.res.ttls[true_vifi] < 255)
2089 goto forward;
2090 }
2091
2023 /* 2092 /*
2024 * Wrong interface: drop packet and (maybe) send PIM assert. 2093 * Wrong interface: drop packet and (maybe) send PIM assert.
2025 */ 2094 */
2026 if (mrt->vif6_table[vif].dev != skb->dev) { 2095 if (mrt->vif6_table[vif].dev != skb->dev) {
2027 int true_vifi;
2028
2029 cache->mfc_un.res.wrong_if++; 2096 cache->mfc_un.res.wrong_if++;
2030 true_vifi = ip6mr_find_vif(mrt, skb->dev);
2031 2097
2032 if (true_vifi >= 0 && mrt->mroute_do_assert && 2098 if (true_vifi >= 0 && mrt->mroute_do_assert &&
2033 /* pimsm uses asserts, when switching from RPT to SPT, 2099 /* pimsm uses asserts, when switching from RPT to SPT,
@@ -2045,14 +2111,32 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
2045 goto dont_forward; 2111 goto dont_forward;
2046 } 2112 }
2047 2113
2114forward:
2048 mrt->vif6_table[vif].pkt_in++; 2115 mrt->vif6_table[vif].pkt_in++;
2049 mrt->vif6_table[vif].bytes_in += skb->len; 2116 mrt->vif6_table[vif].bytes_in += skb->len;
2050 2117
2051 /* 2118 /*
2052 * Forward the frame 2119 * Forward the frame
2053 */ 2120 */
2121 if (ipv6_addr_any(&cache->mf6c_origin) &&
2122 ipv6_addr_any(&cache->mf6c_mcastgrp)) {
2123 if (true_vifi >= 0 &&
2124 true_vifi != cache->mf6c_parent &&
2125 ipv6_hdr(skb)->hop_limit >
2126 cache->mfc_un.res.ttls[cache->mf6c_parent]) {
2127 /* It's an (*,*) entry and the packet is not coming from
2128 * the upstream: forward the packet to the upstream
2129 * only.
2130 */
2131 psend = cache->mf6c_parent;
2132 goto last_forward;
2133 }
2134 goto dont_forward;
2135 }
2054 for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) { 2136 for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) {
2055 if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) { 2137 /* For (*,G) entry, don't forward to the incoming interface */
2138 if ((!ipv6_addr_any(&cache->mf6c_origin) || ct != true_vifi) &&
2139 ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) {
2056 if (psend != -1) { 2140 if (psend != -1) {
2057 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); 2141 struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
2058 if (skb2) 2142 if (skb2)
@@ -2061,6 +2145,7 @@ static int ip6_mr_forward(struct net *net, struct mr6_table *mrt,
2061 psend = ct; 2145 psend = ct;
2062 } 2146 }
2063 } 2147 }
2148last_forward:
2064 if (psend != -1) { 2149 if (psend != -1) {
2065 ip6mr_forward2(net, mrt, skb, cache, psend); 2150 ip6mr_forward2(net, mrt, skb, cache, psend);
2066 return 0; 2151 return 0;
@@ -2096,6 +2181,14 @@ int ip6_mr_input(struct sk_buff *skb)
2096 read_lock(&mrt_lock); 2181 read_lock(&mrt_lock);
2097 cache = ip6mr_cache_find(mrt, 2182 cache = ip6mr_cache_find(mrt,
2098 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); 2183 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr);
2184 if (cache == NULL) {
2185 int vif = ip6mr_find_vif(mrt, skb->dev);
2186
2187 if (vif >= 0)
2188 cache = ip6mr_cache_find_any(mrt,
2189 &ipv6_hdr(skb)->daddr,
2190 vif);
2191 }
2099 2192
2100 /* 2193 /*
2101 * No usable cache entry 2194 * No usable cache entry
@@ -2183,6 +2276,13 @@ int ip6mr_get_route(struct net *net,
2183 2276
2184 read_lock(&mrt_lock); 2277 read_lock(&mrt_lock);
2185 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); 2278 cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr);
2279 if (!cache && skb->dev) {
2280 int vif = ip6mr_find_vif(mrt, skb->dev);
2281
2282 if (vif >= 0)
2283 cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr,
2284 vif);
2285 }
2186 2286
2187 if (!cache) { 2287 if (!cache) {
2188 struct sk_buff *skb2; 2288 struct sk_buff *skb2;