--- zzzz-none-000/linux-3.10.107/net/ipv6/ip6mr.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/net/ipv6/ip6mr.c 2021-11-10 11:53:56.000000000 +0000 @@ -16,6 +16,12 @@ * */ +/** + * Some part of this file is modified by Ikanos Communications. + * + * Copyright (C) 2013-2014 Ikanos Communications. + */ + #include #include #include @@ -123,6 +129,9 @@ static void mroute_clean_tables(struct mr6_table *mrt, bool all); static void ipmr_expire_process(unsigned long arg); +#if IS_ENABLED(CONFIG_FUSIV_KERNEL_AP_2_AP) +int (*ap2apIPv6McastRtPortForwarded_ptr)(struct sk_buff* , struct mif_device *) = NULL; +#endif #ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES #define ip6mr_for_each_table(mrt, net) \ list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list) @@ -1307,6 +1316,32 @@ int line; struct mfc6_cache *c, *next; + + /* IKANOS MLD temp patch starts */ + struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; //all Zero + if(ipv6_addr_equal(&mfc->mf6cc_origin.sin6_addr, &in6addr_any) ) + { + for (line = 0; line < MFC6_LINES; line ++) + { + list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) + { + if ( ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) + break; + } + + if (c) + { + write_lock_bh(&mrt_lock); + list_del(&c->list); + write_unlock_bh(&mrt_lock); + ip6mr_cache_free(c); + return 0; + } + } + + return 0; + } /* IKANOS MLD temp patch ends */ + line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) { @@ -1453,6 +1488,7 @@ struct mfc6_cache *uc, *c; unsigned char ttls[MAXMIFS]; int i; + struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; if (mfc->mf6cc_parent >= MAXMIFS) return -ENFILE; @@ -1463,6 +1499,75 @@ ttls[i] = 1; } + //IKANOS MLD temp patch starts + if(ipv6_addr_equal(&mfc->mf6cc_origin.sin6_addr, &in6addr_any) ) + { + int numSetMifs=0, unsetMif=0; + struct mfc6_cache *next; + for (i = 0; i < MAXMIFS; i++) { + if( ttls[i] == 1) + { + numSetMifs++ ; + } + else + unsetMif = i ; + } + for (line = 0; line < MFC6_LINES; line ++) + { + list_for_each_entry_safe(c, next, &mrt->mfc6_cache_array[line], list) + { + if ( ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) + { + int vifi; + if ( numSetMifs != (MAXMIFS - 1) ) + { + for (vifi = 0; vifi < mrt->maxvif; vifi++) { + if (MIF_EXISTS(mrt, vifi)) { + if(c->mfc_un.res.ttls[vifi] && (c->mfc_un.res.ttls[vifi]<255) ) + { + ttls[vifi] = 1 ; + } + } + } + } + else + { + memset(ttls, 255, MAXMIFS); + for (vifi = 0; vifi < mrt->maxvif; vifi++) { + if (MIF_EXISTS(mrt, vifi)) { + if(c->mfc_un.res.ttls[vifi] && (c->mfc_un.res.ttls[vifi]<255) ) + { + ttls[vifi] = 1 ; + } + } + } + ttls[unsetMif] = 0 ; + for (i = 0; i < mrt->maxvif; i++) { + if(ttls[i] && (ttls[i]<255)) + break; + } + if(i == mrt->maxvif) + { + struct mf6cctl mc; + memset((void*) &mc, 0, sizeof(struct mf6cctl)); + mc.mf6cc_origin.sin6_addr = c->mf6c_origin; + mc.mf6cc_mcastgrp.sin6_addr = c->mf6c_mcastgrp; + ip6mr_mfc_delete(mrt, &mc,parent); + continue; + } + } + write_lock_bh(&mrt_lock); + c->mf6c_parent = mfc->mf6cc_parent; + ip6mr_update_thresholds(mrt, c, ttls); + if (!mrtsock) + c->mfc_flags |= MFC_STATIC; + write_unlock_bh(&mrt_lock); + } + } + } + return 0; + } + //IKANOS MLD temp patch ends line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); @@ -2149,10 +2254,27 @@ /* For (*,G) entry, don't forward to the incoming interface */ if ((!ipv6_addr_any(&cache->mf6c_origin) || ct != true_vifi) && ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) { +#if IS_ENABLED(CONFIG_FUSIV_KERNEL_AP_2_AP) + if (ap2apIPv6McastRtPortForwarded_ptr) + { + if (ap2apIPv6McastRtPortForwarded_ptr(skb , &(mrt->vif6_table[ct])) == 0) + continue; + } +#endif + if (psend != -1) { struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) + if (skb2) { +#if defined(CONFIG_FUSIV_KERNEL_BWMON_STATS) || defined(CONFIG_FUSIV_KERNEL_BWMON_STATS_MODULE) + /* SKB received on WAN is getting duplicated, since all + clones will also pass through bandwidth monitoring + module we reset length in them so that received + length is updated only once i.e.from original SKB. + */ + skb2->apFlowData.bwmonInfo.usReceivedLength = 0 ; +#endif ip6mr_forward2(net, mrt, skb2, cache, psend); + } } psend = ct; } @@ -2505,3 +2627,22 @@ return skb->len; } +#if IS_ENABLED(CONFIG_FUSIV_KERNEL_AP_2_AP) +struct mfc6_cache *ap_ip6mr_cache_find(struct net *net, + const struct in6_addr *origin, + const struct in6_addr *mcastgrp,struct mif_device **vif6_table) +{ + struct mr6_table *mrt; + + mrt = ip6mr_get_table(net, RT6_TABLE_DFLT); + + if (mrt == NULL) { + return NULL; + } + *vif6_table = &mrt->vif6_table[0]; + return ip6mr_cache_find(mrt,origin,mcastgrp); +} + +EXPORT_SYMBOL(ap_ip6mr_cache_find); +EXPORT_SYMBOL(ap2apIPv6McastRtPortForwarded_ptr); +#endif