--- zzzz-none-000/linux-4.1.52/net/ipv6/ip6mr.c 2018-05-28 02:26:45.000000000 +0000 +++ bcm63-7530ax-731/linux-4.1.52/net/ipv6/ip6mr.c 2022-03-02 11:37:13.000000000 +0000 @@ -1014,6 +1014,44 @@ return 0; } +#if defined(CONFIG_BCM_KF_MROUTE) +/* look for (S,G,iif) and then (*,G,iif) */ +static struct mfc6_cache *ip6mr_cache_find_parent(struct mr6_table *mrt, + struct in6_addr *origin, + struct in6_addr *mcastgrp, + mifi_t mifi) +{ + int line = MFC6_HASH(mcastgrp, origin); + struct mfc6_cache *c = NULL; + struct in6_addr nullOrigin; + + list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { + if (ipv6_addr_equal(&c->mf6c_origin, origin) && + ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp) && + (c->mf6c_parent == mifi)) + { + return c; + } + } + + /* for ASM multicast source does not matter so need to check + for an entry with NULL origin as well */ + memset(&nullOrigin, 0, sizeof(struct in6_addr)); + line = MFC6_HASH(mcastgrp, &nullOrigin); + + list_for_each_entry(c, &mrt->mfc6_cache_array[line], list) { + if (ipv6_addr_equal(&c->mf6c_origin, &nullOrigin) && + ipv6_addr_equal(&c->mf6c_mcastgrp, mcastgrp) && + (c->mf6c_parent == mifi)) + { + return c; + } + } + + return NULL; +} +#endif + static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, const struct in6_addr *origin, const struct in6_addr *mcastgrp) @@ -1045,6 +1083,7 @@ return NULL; } +#if !defined(CONFIG_BCM_KF_MROUTE) /* Look for a (*,G) entry */ static struct mfc6_cache *ip6mr_cache_find_any(struct mr6_table *mrt, struct in6_addr *mcastgrp, @@ -1072,6 +1111,7 @@ skip: return ip6mr_cache_find_any_parent(mrt, mifi); } +#endif /* * Allocate a multicast cache entry @@ -2051,7 +2091,12 @@ * result in receiving multiple packets. */ dev = vif->dev; +#if defined(CONFIG_BCM_KF_MLD) + /* skb->dev is the soruce device. It should not be + set to the destination device */ +#else skb->dev = dev; +#endif vif->pkt_out++; vif->bytes_out += skb->len; @@ -2159,7 +2204,14 @@ if (psend != -1) { struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + { + blog_clone(skb, blog_ptr(skb2)); +#endif ip6mr_forward2(net, mrt, skb2, cache, psend); +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) + } +#endif } psend = ct; } @@ -2197,6 +2249,18 @@ } read_lock(&mrt_lock); +#if defined(CONFIG_BCM_KF_MROUTE) + /* mroute6 should not apply to MLD traffic + in addition it does not make sense for TCP protocol to be used + for multicast so just check for UDP */ + cache = NULL; + if( ipv6_hdr(skb)->nexthdr == IPPROTO_UDP ) + { + mifi_t mifi = ip6mr_find_vif(mrt, skb->dev); + cache = ip6mr_cache_find_parent(mrt, &ipv6_hdr(skb)->saddr, + &ipv6_hdr(skb)->daddr, mifi); + } +#else cache = ip6mr_cache_find(mrt, &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr); if (!cache) { @@ -2207,7 +2271,7 @@ &ipv6_hdr(skb)->daddr, vif); } - +#endif /* * No usable cache entry */ @@ -2280,8 +2344,14 @@ return 1; } +#if defined(CONFIG_BCM_KF_MROUTE) +int ip6mr_get_route(struct net *net, + struct sk_buff *skb, struct rtmsg *rtm, int nowait, + int ifIndex) +#else int ip6mr_get_route(struct net *net, struct sk_buff *skb, struct rtmsg *rtm, int nowait) +#endif { int err; struct mr6_table *mrt; @@ -2293,6 +2363,26 @@ return -ENOENT; read_lock(&mrt_lock); +#if defined(CONFIG_BCM_KF_MROUTE) + /* mroute6 should not apply to MLD traffic + in addition it does not make sense for TCP protocol to be used + for multicast so just check for UDP */ + cache = NULL; + if( (skb->dev == NULL) || (ipv6_hdr(skb) == NULL) || + (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP) ) + { + struct net_device *dev = dev_get_by_index(net, ifIndex); + if (dev) { + mifi_t mifi = ip6mr_find_vif(mrt, dev); + if (mifi >= 0) + { + cache = ip6mr_cache_find_parent(mrt, &rt->rt6i_src.addr, + &rt->rt6i_dst.addr, mifi); + } + dev_put(dev); + } + } +#else cache = ip6mr_cache_find(mrt, &rt->rt6i_src.addr, &rt->rt6i_dst.addr); if (!cache && skb->dev) { int vif = ip6mr_find_vif(mrt, skb->dev); @@ -2301,7 +2391,7 @@ cache = ip6mr_cache_find_any(mrt, &rt->rt6i_dst.addr, vif); } - +#endif if (!cache) { struct sk_buff *skb2; struct ipv6hdr *iph;