]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv4/udp.c
net: use the macros defined for the members of flowi
[net-next-2.6.git] / net / ipv4 / udp.c
index 32e0bef60d0afdbedd3d4cbdd3c57a9f9beafcdc..b37181da487cc22164f8b9f6fe0f160ee742a36f 100644 (file)
 struct udp_table udp_table __read_mostly;
 EXPORT_SYMBOL(udp_table);
 
-int sysctl_udp_mem[3] __read_mostly;
+long sysctl_udp_mem[3] __read_mostly;
 EXPORT_SYMBOL(sysctl_udp_mem);
 
 int sysctl_udp_rmem_min __read_mostly;
@@ -119,7 +119,7 @@ EXPORT_SYMBOL(sysctl_udp_rmem_min);
 int sysctl_udp_wmem_min __read_mostly;
 EXPORT_SYMBOL(sysctl_udp_wmem_min);
 
-atomic_t udp_memory_allocated;
+atomic_long_t udp_memory_allocated;
 EXPORT_SYMBOL(udp_memory_allocated);
 
 #define MAX_UDP_PORTS 65536
@@ -430,7 +430,7 @@ begin:
 
        if (result) {
 exact_match:
-               if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))
+               if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2)))
                        result = NULL;
                else if (unlikely(compute_score2(result, net, saddr, sport,
                                  daddr, hnum, dif) < badness)) {
@@ -500,7 +500,7 @@ begin:
                goto begin;
 
        if (result) {
-               if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))
+               if (unlikely(!atomic_inc_not_zero_hint(&result->sk_refcnt, 2)))
                        result = NULL;
                else if (unlikely(compute_score(result, net, saddr, hnum, sport,
                                  daddr, dport, dif) < badness)) {
@@ -797,7 +797,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                return -EOPNOTSUPP;
 
        ipc.opt = NULL;
-       ipc.shtx.flags = 0;
+       ipc.tx_flags = 0;
 
        if (up->pending) {
                /*
@@ -845,7 +845,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        ipc.addr = inet->inet_saddr;
 
        ipc.oif = sk->sk_bound_dev_if;
-       err = sock_tx_timestamp(msg, sk, &ipc.shtx);
+       err = sock_tx_timestamp(sk, &ipc.tx_flags);
        if (err)
                return err;
        if (msg->msg_controllen) {
@@ -890,15 +890,13 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        if (rt == NULL) {
                struct flowi fl = { .oif = ipc.oif,
                                    .mark = sk->sk_mark,
-                                   .nl_u = { .ip4_u =
-                                             { .daddr = faddr,
-                                               .saddr = saddr,
-                                               .tos = tos } },
+                                   .fl4_dst = faddr,
+                                   .fl4_src = saddr,
+                                   .fl4_tos = tos,
                                    .proto = sk->sk_protocol,
                                    .flags = inet_sk_flowi_flags(sk),
-                                   .uli_u = { .ports =
-                                              { .sport = inet->inet_sport,
-                                                .dport = dport } } };
+                                   .fl_ip_sport = inet->inet_sport,
+                                   .fl_ip_dport = dport };
                struct net *net = sock_net(sk);
 
                security_sk_classify_flow(sk, &fl);
@@ -1260,6 +1258,49 @@ void udp_lib_unhash(struct sock *sk)
 }
 EXPORT_SYMBOL(udp_lib_unhash);
 
+/*
+ * inet_rcv_saddr was changed, we must rehash secondary hash
+ */
+void udp_lib_rehash(struct sock *sk, u16 newhash)
+{
+       if (sk_hashed(sk)) {
+               struct udp_table *udptable = sk->sk_prot->h.udp_table;
+               struct udp_hslot *hslot, *hslot2, *nhslot2;
+
+               hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
+               nhslot2 = udp_hashslot2(udptable, newhash);
+               udp_sk(sk)->udp_portaddr_hash = newhash;
+               if (hslot2 != nhslot2) {
+                       hslot = udp_hashslot(udptable, sock_net(sk),
+                                            udp_sk(sk)->udp_port_hash);
+                       /* we must lock primary chain too */
+                       spin_lock_bh(&hslot->lock);
+
+                       spin_lock(&hslot2->lock);
+                       hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
+                       hslot2->count--;
+                       spin_unlock(&hslot2->lock);
+
+                       spin_lock(&nhslot2->lock);
+                       hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
+                                                &nhslot2->head);
+                       nhslot2->count++;
+                       spin_unlock(&nhslot2->lock);
+
+                       spin_unlock_bh(&hslot->lock);
+               }
+       }
+}
+EXPORT_SYMBOL(udp_lib_rehash);
+
+static void udp_v4_rehash(struct sock *sk)
+{
+       u16 new_hash = udp4_portaddr_hash(sock_net(sk),
+                                         inet_sk(sk)->inet_rcv_saddr,
+                                         inet_sk(sk)->inet_num);
+       udp_lib_rehash(sk, new_hash);
+}
+
 static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
@@ -1370,7 +1411,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
        }
 
-       if (sk->sk_filter) {
+       if (rcu_dereference_raw(sk->sk_filter)) {
                if (udp_lib_checksum_complete(skb))
                        goto drop;
        }
@@ -1843,6 +1884,7 @@ struct proto udp_prot = {
        .backlog_rcv       = __udp_queue_rcv_skb,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v4_rehash,
        .get_port          = udp_v4_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,