Merge "bnx2x: allow adding VLANs while interface is down"
[kvmfornfv.git] / kernel / net / ipv6 / udp.c
index e51fc3e..dfa85e7 100644 (file)
@@ -182,10 +182,12 @@ static inline int compute_score(struct sock *sk, struct net *net,
                score++;
        }
 
+       if (sk->sk_incoming_cpu == raw_smp_processor_id())
+               score++;
+
        return score;
 }
 
-#define SCORE2_MAX (1 + 1 + 1)
 static inline int compute_score2(struct sock *sk, struct net *net,
                                 const struct in6_addr *saddr, __be16 sport,
                                 const struct in6_addr *daddr,
@@ -223,6 +225,9 @@ static inline int compute_score2(struct sock *sk, struct net *net,
                score++;
        }
 
+       if (sk->sk_incoming_cpu == raw_smp_processor_id())
+               score++;
+
        return score;
 }
 
@@ -251,8 +256,7 @@ begin:
                                hash = udp6_ehashfn(net, daddr, hnum,
                                                    saddr, sport);
                                matches = 1;
-                       } else if (score == SCORE2_MAX)
-                               goto exact_match;
+                       }
                } else if (score == badness && reuseport) {
                        matches++;
                        if (reciprocal_scale(hash, matches) == 0)
@@ -269,7 +273,6 @@ begin:
                goto begin;
 
        if (result) {
-exact_match:
                if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2)))
                        result = NULL;
                else if (unlikely(compute_score2(result, net, saddr, sport,
@@ -399,6 +402,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
        int peeked, off = 0;
        int err;
        int is_udplite = IS_UDPLITE(sk);
+       bool checksum_valid = false;
        int is_udp4;
        bool slow;
 
@@ -430,11 +434,12 @@ try_again:
         */
 
        if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
-               if (udp_lib_checksum_complete(skb))
+               checksum_valid = !udp_lib_checksum_complete(skb);
+               if (!checksum_valid)
                        goto csum_copy_err;
        }
 
-       if (skb_csum_unnecessary(skb))
+       if (checksum_valid || skb_csum_unnecessary(skb))
                err = skb_copy_datagram_msg(skb, sizeof(struct udphdr),
                                            msg, copied);
        else {
@@ -493,7 +498,8 @@ try_again:
 
        if (is_udp4) {
                if (inet->cmsg_flags)
-                       ip_cmsg_recv(msg, skb);
+                       ip_cmsg_recv_offset(msg, skb,
+                                           sizeof(struct udphdr), off);
        } else {
                if (np->rxopt.all)
                        ip6_datagram_recv_specific_ctl(sk, msg, skb);
@@ -644,7 +650,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
                /* if we're overly short, let UDP handle it */
                encap_rcv = ACCESS_ONCE(up->encap_rcv);
-               if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+               if (encap_rcv) {
                        int ret;
 
                        /* Verify checksum before giving to encap */
@@ -834,8 +840,8 @@ start_lookup:
                flush_stack(stack, count, skb, count - 1);
        } else {
                if (!inner_flushed)
-                       UDP_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI,
-                                        proto == IPPROTO_UDPLITE);
+                       UDP6_INC_STATS_BH(net, UDP_MIB_IGNOREDMULTI,
+                                         proto == IPPROTO_UDPLITE);
                consume_skb(skb);
        }
        return 0;
@@ -913,11 +919,9 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
                ret = udpv6_queue_rcv_skb(sk, skb);
                sock_put(sk);
 
-               /* a return value > 0 means to resubmit the input, but
-                * it wants the return to be -protocol, or 0
-                */
+               /* a return value > 0 means to resubmit the input */
                if (ret > 0)
-                       return -ret;
+                       return ret;
 
                return 0;
        }
@@ -1107,6 +1111,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
        struct in6_addr *daddr, *final_p, final;
        struct ipv6_txoptions *opt = NULL;
+       struct ipv6_txoptions *opt_to_free = NULL;
        struct ip6_flowlabel *flowlabel = NULL;
        struct flowi6 fl6;
        struct dst_entry *dst;
@@ -1260,8 +1265,10 @@ do_udp_sendmsg:
                        opt = NULL;
                connected = 0;
        }
-       if (!opt)
-               opt = np->opt;
+       if (!opt) {
+               opt = txopt_get(np);
+               opt_to_free = opt;
+       }
        if (flowlabel)
                opt = fl6_merge_options(&opt_space, flowlabel, opt);
        opt = ipv6_fixup_options(&opt_space, opt);
@@ -1370,6 +1377,7 @@ release_dst:
 out:
        dst_release(dst);
        fl6_sock_release(flowlabel);
+       txopt_put(opt_to_free);
        if (!err)
                return len;
        /*
@@ -1496,7 +1504,8 @@ int __net_init udp6_proc_init(struct net *net)
        return udp_proc_register(net, &udp6_seq_afinfo);
 }
 
-void udp6_proc_exit(struct net *net) {
+void udp6_proc_exit(struct net *net)
+{
        udp_proc_unregister(net, &udp6_seq_afinfo);
 }
 #endif /* CONFIG_PROC_FS */