rxrpc: Fix use of Don't Fragment flag
[platform/kernel/linux-starfive.git] / net / rxrpc / local_object.c
index 270b63d..34d3073 100644 (file)
@@ -37,6 +37,17 @@ static void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, int err,
 }
 
 /*
+ * Set or clear the Don't Fragment flag on a socket.
+ */
+void rxrpc_local_dont_fragment(const struct rxrpc_local *local, bool set)
+{
+       if (set)
+               ip_sock_set_mtu_discover(local->socket->sk, IP_PMTUDISC_DO);
+       else
+               ip_sock_set_mtu_discover(local->socket->sk, IP_PMTUDISC_DONT);
+}
+
+/*
  * Compare a local to an address.  Return -ve, 0 or +ve to indicate less than,
  * same or greater than.
  *
@@ -82,31 +93,61 @@ static long rxrpc_local_cmp_key(const struct rxrpc_local *local,
        }
 }
 
+static void rxrpc_client_conn_reap_timeout(struct timer_list *timer)
+{
+       struct rxrpc_local *local =
+               container_of(timer, struct rxrpc_local, client_conn_reap_timer);
+
+       if (!local->kill_all_client_conns &&
+           test_and_set_bit(RXRPC_CLIENT_CONN_REAP_TIMER, &local->client_conn_flags))
+               rxrpc_wake_up_io_thread(local);
+}
+
 /*
  * Allocate a new local endpoint.
  */
-static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
+static struct rxrpc_local *rxrpc_alloc_local(struct net *net,
                                             const struct sockaddr_rxrpc *srx)
 {
        struct rxrpc_local *local;
+       u32 tmp;
 
        local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL);
        if (local) {
                refcount_set(&local->ref, 1);
                atomic_set(&local->active_users, 1);
-               local->rxnet = rxnet;
+               local->net = net;
+               local->rxnet = rxrpc_net(net);
                INIT_HLIST_NODE(&local->link);
-               init_rwsem(&local->defrag_sem);
                init_completion(&local->io_thread_ready);
+#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
+               skb_queue_head_init(&local->rx_delay_queue);
+#endif
                skb_queue_head_init(&local->rx_queue);
+               INIT_LIST_HEAD(&local->conn_attend_q);
                INIT_LIST_HEAD(&local->call_attend_q);
+
                local->client_bundles = RB_ROOT;
                spin_lock_init(&local->client_bundles_lock);
+               local->kill_all_client_conns = false;
+               INIT_LIST_HEAD(&local->idle_client_conns);
+               timer_setup(&local->client_conn_reap_timer,
+                           rxrpc_client_conn_reap_timeout, 0);
+
                spin_lock_init(&local->lock);
                rwlock_init(&local->services_lock);
                local->debug_id = atomic_inc_return(&rxrpc_debug_id);
                memcpy(&local->srx, srx, sizeof(*srx));
                local->srx.srx_service = 0;
+               idr_init(&local->conn_ids);
+               get_random_bytes(&tmp, sizeof(tmp));
+               tmp &= 0x3fffffff;
+               if (tmp == 0)
+                       tmp = 1;
+               idr_set_cursor(&local->conn_ids, tmp);
+               INIT_LIST_HEAD(&local->new_client_calls);
+               spin_lock_init(&local->client_call_lock);
+
                trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, 1);
        }
 
@@ -173,7 +214,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
                ip_sock_set_recverr(usk);
 
                /* we want to set the don't fragment bit */
-               ip_sock_set_mtu_discover(usk, IP_PMTUDISC_DO);
+               rxrpc_local_dont_fragment(local, true);
 
                /* We want receive timestamps. */
                sock_enable_timestamps(usk);
@@ -248,7 +289,7 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net,
                goto found;
        }
 
-       local = rxrpc_alloc_local(rxnet, srx);
+       local = rxrpc_alloc_local(net, srx);
        if (!local)
                goto nomem;
 
@@ -406,7 +447,11 @@ void rxrpc_destroy_local(struct rxrpc_local *local)
        /* At this point, there should be no more packets coming in to the
         * local endpoint.
         */
+#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
+       rxrpc_purge_queue(&local->rx_delay_queue);
+#endif
        rxrpc_purge_queue(&local->rx_queue);
+       rxrpc_purge_client_connections(local);
 }
 
 /*