--- zzzz-none-000/linux-4.1.38/net/ipv6/netfilter.c 2017-01-18 18:48:06.000000000 +0000 +++ bcm63-7582-715/linux-4.1.38/net/ipv6/netfilter.c 2020-11-25 10:06:48.000000000 +0000 @@ -32,6 +32,16 @@ }; int err; +#if defined(CONFIG_BCM_KF_NETFILTER) + /* keep original output dev if destination is multicast/linklocal */ + if ( ( fl6.flowi6_oif == 0 ) && ((skb_dst(skb)->dev)) + && ( __ipv6_addr_type(&fl6.daddr) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)) + ) + { + fl6.flowi6_oif = (skb_dst(skb)->dev)->ifindex; + } +#endif + dst = ip6_route_output(net, skb->sk, &fl6); err = dst->error; if (err) { @@ -135,11 +145,28 @@ { const struct ipv6hdr *ip6h = ipv6_hdr(skb); __sum16 csum = 0; +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + struct in6_addr sAddr; + struct in6_addr dAddr; + + memcpy(&sAddr, &ip6h->saddr, sizeof(struct in6_addr)); + memcpy(&dAddr, &ip6h->daddr, sizeof(struct in6_addr)); +#endif switch (skb->ip_summed) { case CHECKSUM_COMPLETE: if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN) break; +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + if (!csum_ipv6_magic(&sAddr, &dAddr, + skb->len - dataoff, protocol, + csum_sub(skb->csum, + skb_checksum(skb, 0, + dataoff, 0)))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + break; + } +#else if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb->len - dataoff, protocol, csum_sub(skb->csum, @@ -148,8 +175,18 @@ skb->ip_summed = CHECKSUM_UNNECESSARY; break; } +#endif /* fall through */ case CHECKSUM_NONE: +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + skb->csum = ~csum_unfold( + csum_ipv6_magic(&sAddr, &dAddr, + skb->len - dataoff, + protocol, + csum_sub(0, + skb_checksum(skb, 0, + dataoff, 0)))); +#else skb->csum = ~csum_unfold( csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb->len - dataoff, @@ -157,6 +194,7 @@ csum_sub(0, skb_checksum(skb, 0, dataoff, 0)))); +#endif csum = __skb_checksum_complete(skb); } return csum; @@ -170,6 +208,13 @@ const struct ipv6hdr *ip6h = ipv6_hdr(skb); __wsum hsum; __sum16 csum = 0; +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + struct in6_addr sAddr; + struct in6_addr dAddr; + + memcpy(&sAddr, &ip6h->saddr, sizeof(struct in6_addr)); + memcpy(&dAddr, &ip6h->daddr, sizeof(struct in6_addr)); +#endif switch (skb->ip_summed) { case CHECKSUM_COMPLETE: @@ -178,11 +223,19 @@ /* fall through */ case CHECKSUM_NONE: hsum = skb_checksum(skb, 0, dataoff, 0); +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + skb->csum = ~csum_unfold(csum_ipv6_magic(&sAddr, + &dAddr, + skb->len - dataoff, + protocol, + csum_sub(0, hsum))); +#else skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb->len - dataoff, protocol, csum_sub(0, hsum))); +#endif skb->ip_summed = CHECKSUM_NONE; return __skb_checksum_complete_head(skb, dataoff + len); }