]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/batman-adv/icmp_socket.c
net: rfs: enable RFS before first data packet is received
[karo-tx-linux.git] / net / batman-adv / icmp_socket.c
index 34ce56c358e5ee750f13395eee1f395d0029979d..fa22ba2bb832ac97b58b4b35c36830fceb7e75ee 100644 (file)
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
 {
        struct socket_client *socket_client = file->private_data;
        struct bat_priv *bat_priv = socket_client->bat_priv;
+       struct hard_iface *primary_if = NULL;
        struct sk_buff *skb;
        struct icmp_packet_rr *icmp_packet;
 
@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
                return -EINVAL;
        }
 
-       if (!bat_priv->primary_if)
-               return -EFAULT;
+       primary_if = primary_if_get_selected(bat_priv);
+
+       if (!primary_if) {
+               len = -EFAULT;
+               goto out;
+       }
 
        if (len >= sizeof(struct icmp_packet_rr))
                packet_len = sizeof(struct icmp_packet_rr);
 
        skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
-       if (!skb)
-               return -ENOMEM;
+       if (!skb) {
+               len = -ENOMEM;
+               goto out;
+       }
 
        skb_reserve(skb, sizeof(struct ethhdr));
        icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
@@ -218,23 +225,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
        if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
                goto dst_unreach;
 
-       rcu_read_lock();
        orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
-
        if (!orig_node)
-               goto unlock;
-
-       neigh_node = orig_node->router;
+               goto dst_unreach;
 
+       neigh_node = orig_node_get_router(orig_node);
        if (!neigh_node)
-               goto unlock;
-
-       if (!atomic_inc_not_zero(&neigh_node->refcount)) {
-               neigh_node = NULL;
-               goto unlock;
-       }
-
-       rcu_read_unlock();
+               goto dst_unreach;
 
        if (!neigh_node->if_incoming)
                goto dst_unreach;
@@ -243,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
                goto dst_unreach;
 
        memcpy(icmp_packet->orig,
-              bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+              primary_if->net_dev->dev_addr, ETH_ALEN);
 
        if (packet_len == sizeof(struct icmp_packet_rr))
                memcpy(icmp_packet->rr,
@@ -252,14 +249,14 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
        send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
        goto out;
 
-unlock:
-       rcu_read_unlock();
 dst_unreach:
        icmp_packet->msg_type = DESTINATION_UNREACHABLE;
        bat_socket_add_packet(socket_client, icmp_packet, packet_len);
 free_skb:
        kfree_skb(skb);
 out:
+       if (primary_if)
+               hardif_free_ref(primary_if);
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)