--- zzzz-none-000/linux-4.1.38/net/ipv6/raw.c 2017-01-18 18:48:06.000000000 +0000 +++ bcm63-7582-715/linux-4.1.38/net/ipv6/raw.c 2020-11-25 10:06:48.000000000 +0000 @@ -157,16 +157,26 @@ */ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) { +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + struct in6_addr saddr; + struct in6_addr daddr; +#else const struct in6_addr *saddr; const struct in6_addr *daddr; +#endif struct sock *sk; bool delivered = false; __u8 hash; struct net *net; +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + memcpy(&saddr, &ipv6_hdr(skb)->saddr, sizeof(struct in6_addr)); + memcpy(&daddr, &ipv6_hdr(skb)->daddr, sizeof(struct in6_addr)); +#else saddr = &ipv6_hdr(skb)->saddr; daddr = saddr + 1; +#endif hash = nexthdr & (RAW_HTABLE_SIZE - 1); read_lock(&raw_v6_hashinfo.lock); @@ -176,8 +186,12 @@ goto out; net = dev_net(skb->dev); +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + sk = __raw_v6_lookup(net, sk, nexthdr, &daddr, &saddr, inet6_iif(skb)); +#else sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb)); +#endif while (sk) { int filtered; @@ -219,8 +233,13 @@ rawv6_rcv(sk, clone); } } +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, &daddr, &saddr, + inet6_iif(skb)); +#else sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, inet6_iif(skb)); +#endif } out: read_unlock(&raw_v6_hashinfo.lock); @@ -414,6 +433,10 @@ { struct inet_sock *inet = inet_sk(sk); struct raw6_sock *rp = raw6_sk(sk); +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + struct in6_addr dstAddr; + struct in6_addr srcAddr; +#endif if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { atomic_inc(&sk->sk_drops); @@ -424,19 +447,38 @@ if (!rp->checksum) skb->ip_summed = CHECKSUM_UNNECESSARY; +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + memcpy(&srcAddr, &ipv6_hdr(skb)->saddr, sizeof(struct in6_addr)); + memcpy(&dstAddr, &ipv6_hdr(skb)->daddr, sizeof(struct in6_addr)); +#endif + if (skb->ip_summed == CHECKSUM_COMPLETE) { skb_postpull_rcsum(skb, skb_network_header(skb), skb_network_header_len(skb)); +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + if (!csum_ipv6_magic(&srcAddr, &dstAddr, + skb->len, inet->inet_num, skb->csum)) + skb->ip_summed = CHECKSUM_UNNECESSARY; +#else + if (!csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->len, inet->inet_num, skb->csum)) skb->ip_summed = CHECKSUM_UNNECESSARY; +#endif } if (!skb_csum_unnecessary(skb)) +#if defined(CONFIG_MIPS_BCM963XX) && defined(CONFIG_BCM_KF_UNALIGNED_EXCEPTION) + skb->csum = ~csum_unfold(csum_ipv6_magic(&srcAddr, + &dstAddr, + skb->len, + inet->inet_num, 0)); +#else skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr, skb->len, inet->inet_num, 0)); +#endif if (inet->hdrincl) { if (skb_checksum_complete(skb)) { @@ -968,6 +1010,7 @@ switch (optname) { case IPV6_CHECKSUM: +#if !defined(CONFIG_BCM_KF_IP) if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && level == IPPROTO_IPV6) { /* @@ -980,6 +1023,7 @@ */ return -EINVAL; } +#endif /* You may get strange result with a positive odd offset; RFC2292bis agrees with me. */