--- zzzz-none-000/linux-2.6.28.10/net/ipv6/ip6mr.c 2009-05-02 18:54:43.000000000 +0000 +++ fusiv-7390-686/linux-2.6.28.10/net/ipv6/ip6mr.c 2012-02-14 14:37:49.000000000 +0000 @@ -99,6 +99,9 @@ #ifdef CONFIG_IPV6_PIMSM_V2 static struct inet6_protocol pim6_protocol; #endif +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) +int (*ap2apIPv6McastRtPortForwarded_ptr)(struct sk_buff* , int) = NULL; +#endif static struct timer_list ipmr_expire_timer; @@ -797,6 +800,7 @@ * Add our header */ skb_put(skb, sizeof(*msg)); + /* skb->data is not moved hence ; n/w and transport are pointed to same location*/ skb_reset_transport_header(skb); msg = (struct mrt6msg *)skb_transport_header(skb); @@ -810,7 +814,9 @@ skb->dst = dst_clone(pkt->dst); skb->ip_summed = CHECKSUM_UNNECESSARY; +#if 0 skb_pull(skb, sizeof(struct ipv6hdr)); +#endif } if (mroute6_socket == NULL) { @@ -912,6 +918,32 @@ int line; struct mfc6_cache *c, **cp; + /* 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 ++) + { + for (cp=&mfc6_cache_array[line]; (c=*cp) != NULL; cp = &c->next) + { + if ( ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) + break; + } + + if (c) + { + write_lock_bh(&mrt_lock); + *cp = c->next; + write_unlock_bh(&mrt_lock); + + kmem_cache_free(mrt_cachep, c); + return 0; + } + } + + return 0; + } /* IKANOS MLD temp patch ends */ + line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { @@ -1011,6 +1043,7 @@ unsigned char ttls[MAXMIFS]; int i; + struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; memset(ttls, 255, MAXMIFS); for (i = 0; i < MAXMIFS; i++) { if (IF_ISSET(i, &mfc->mf6cc_ifset)) @@ -1018,6 +1051,82 @@ } + //IKANOS MLD temp patch starts + if(ipv6_addr_equal(&mfc->mf6cc_origin.sin6_addr, &in6addr_any) ) + { + int numSetMifs=0, unsetMif=0; + for (i = 0; i < MAXMIFS; i++) { + if( ttls[i] == 1) + { + numSetMifs++ ; + } + else + unsetMif = i ; + } + for (line = 0; line < MFC6_LINES; line ++) + { + for (cp=&mfc6_cache_array[line]; (c=*cp) != NULL; ) // cp = &c->next) + { + if ( ipv6_addr_equal(&c->mf6c_mcastgrp, &mfc->mf6cc_mcastgrp.sin6_addr)) + { + int vifi; + if ( numSetMifs != (MAXMIFS - 1) ) + { + for (vifi = 0; vifi < maxvif; vifi++) { + if (MIF_EXISTS(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 < maxvif; vifi++) { + if (MIF_EXISTS(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 < maxvif; i++) { + if(ttls[i] && (ttls[i]<255)) + break; + } + if(i == 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; + /* as c will be no more available after calling delete */ + cp = &c->next; + ip6mr_mfc_delete( &mc ) ; + continue; + } + } + write_lock_bh(&mrt_lock); + c->mf6c_parent = mfc->mf6cc_parent; + ip6mr_update_thresholds(c, ttls); + if (!mrtsock) + c->mfc_flags |= MFC_STATIC; + write_unlock_bh(&mrt_lock); + } + cp = &c->next; + } + + + } + + return 0; + } + //IKANOS MLD temp patch ends + line = MFC6_HASH(&mfc->mf6cc_mcastgrp.sin6_addr, &mfc->mf6cc_origin.sin6_addr); for (cp = &mfc6_cache_array[line]; (c = *cp) != NULL; cp = &c->next) { @@ -1046,6 +1155,7 @@ c->mf6c_origin = mfc->mf6cc_origin.sin6_addr; c->mf6c_mcastgrp = mfc->mf6cc_mcastgrp.sin6_addr; c->mf6c_parent = mfc->mf6cc_parent; + ip6mr_update_thresholds(c, ttls); if (!mrtsock) c->mfc_flags |= MFC_STATIC; @@ -1517,6 +1627,13 @@ */ for (ct = cache->mfc_un.res.maxvif - 1; ct >= cache->mfc_un.res.minvif; ct--) { if (ipv6_hdr(skb)->hop_limit > cache->mfc_un.res.ttls[ct]) { +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) + if (ap2apIPv6McastRtPortForwarded_ptr) + { + if (ap2apIPv6McastRtPortForwarded_ptr(skb , ct) == 0) + continue; + } +#endif if (psend != -1) { struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) @@ -1671,4 +1788,8 @@ read_unlock(&mrt_lock); return err; } - +#if defined(CONFIG_FUSIV_KERNEL_AP_2_AP) || defined(CONFIG_FUSIV_KERNEL_AP_2_AP_MODULE) +EXPORT_SYMBOL(ip6mr_cache_find); +EXPORT_SYMBOL(vif6_table); +EXPORT_SYMBOL(ap2apIPv6McastRtPortForwarded_ptr); +#endif