Loading net/batman-adv/aggregation.c +0 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, return false; } #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* create a new aggregated packet and add this packet to it */ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, unsigned long send_time, bool direct_link, Loading net/batman-adv/gateway_client.c +27 −18 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv) return; curr_gw = gw_get_selected_gw_node(bat_priv); if (!curr_gw) if (curr_gw) goto out; rcu_read_lock(); Loading Loading @@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv, struct hlist_node *node; struct gw_node *gw_node, *curr_gw; /** * Note: We don't need a NULL check here, since curr_gw never gets * dereferenced. If curr_gw is NULL we also should not exit as we may * have this gateway in our list (duplication check!) even though we * have no currently selected gateway. */ curr_gw = gw_get_selected_gw_node(bat_priv); if (!curr_gw) goto out; rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { Loading Loading @@ -350,7 +354,7 @@ void gw_node_update(struct bat_priv *bat_priv, gw_deselect(bat_priv); unlock: rcu_read_unlock(); out: if (curr_gw) gw_node_free_ref(curr_gw); } Loading Loading @@ -435,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hard_iface *primary_if; struct gw_node *gw_node; struct hlist_node *node; int gw_count = 0; int gw_count = 0, ret = 0; if (!bat_priv->primary_if) { return seq_printf(seq, "BATMAN mesh %s disabled - please " primary_if = primary_if_get_selected(bat_priv); if (!primary_if) { ret = seq_printf(seq, "BATMAN mesh %s disabled - please " "specify interfaces to enable it\n", net_dev->name); goto out; } if (bat_priv->primary_if->if_status != IF_ACTIVE) { return seq_printf(seq, "BATMAN mesh %s disabled - " if (primary_if->if_status != IF_ACTIVE) { ret = seq_printf(seq, "BATMAN mesh %s disabled - " "primary interface not active\n", net_dev->name); goto out; } seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", "Gateway", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, bat_priv->primary_if->net_dev->name, bat_priv->primary_if->net_dev->dev_addr, net_dev->name); primary_if->net_dev->name, primary_if->net_dev->dev_addr, net_dev->name); rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { Loading @@ -476,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) if (gw_count == 0) seq_printf(seq, "No gateways in range ...\n"); return 0; out: if (primary_if) hardif_free_ref(primary_if); return ret; } int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) Loading net/batman-adv/hard-interface.c +57 −26 Original line number Diff line number Diff line Loading @@ -110,47 +110,60 @@ static struct hard_iface *hardif_get_active(struct net_device *soft_iface) return hard_iface; } static void update_primary_addr(struct bat_priv *bat_priv) static void primary_if_update_addr(struct bat_priv *bat_priv) { struct vis_packet *vis_packet; struct hard_iface *primary_if; primary_if = primary_if_get_selected(bat_priv); if (!primary_if) goto out; vis_packet = (struct vis_packet *) bat_priv->my_vis_info->skb_packet->data; memcpy(vis_packet->vis_orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); primary_if->net_dev->dev_addr, ETH_ALEN); out: if (primary_if) hardif_free_ref(primary_if); } static void set_primary_if(struct bat_priv *bat_priv, struct hard_iface *hard_iface) static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *new_hard_iface) { struct hard_iface *curr_hard_iface; struct batman_packet *batman_packet; struct hard_iface *old_if; if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) hard_iface = NULL; spin_lock_bh(&hardif_list_lock); old_if = bat_priv->primary_if; bat_priv->primary_if = hard_iface; if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) new_hard_iface = NULL; if (old_if) hardif_free_ref(old_if); curr_hard_iface = bat_priv->primary_if; rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); if (!bat_priv->primary_if) return; if (curr_hard_iface) hardif_free_ref(curr_hard_iface); batman_packet = (struct batman_packet *)(hard_iface->packet_buff); if (!new_hard_iface) goto out; batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); batman_packet->flags = PRIMARIES_FIRST_HOP; batman_packet->ttl = TTL; update_primary_addr(bat_priv); primary_if_update_addr(bat_priv); /*** * hacky trick to make sure that we send the HNA information via * our new primary interface */ atomic_set(&bat_priv->hna_local_changed, 1); out: spin_unlock_bh(&hardif_list_lock); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) Loading Loading @@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface) static void hardif_activate_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv; struct hard_iface *primary_if = NULL; if (hard_iface->if_status != IF_INACTIVE) return; goto out; bat_priv = netdev_priv(hard_iface->soft_iface); Loading @@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) * the first active interface becomes our primary interface or * the next active interface after the old primay interface was removed */ if (!bat_priv->primary_if) set_primary_if(bat_priv, hard_iface); primary_if = primary_if_get_selected(bat_priv); if (!primary_if) primary_if_select(bat_priv, hard_iface); bat_info(hard_iface->soft_iface, "Interface activated: %s\n", hard_iface->net_dev->name); update_min_mtu(hard_iface->soft_iface); return; out: if (primary_if) hardif_free_ref(primary_if); } static void hardif_deactivate_interface(struct hard_iface *hard_iface) Loading Loading @@ -386,12 +404,13 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) void hardif_disable_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct hard_iface *primary_if = NULL; if (hard_iface->if_status == IF_ACTIVE) hardif_deactivate_interface(hard_iface); if (hard_iface->if_status != IF_INACTIVE) return; goto out; bat_info(hard_iface->soft_iface, "Removing interface: %s\n", hard_iface->net_dev->name); Loading @@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface) bat_priv->num_ifaces--; orig_hash_del_if(hard_iface, bat_priv->num_ifaces); if (hard_iface == bat_priv->primary_if) { primary_if = primary_if_get_selected(bat_priv); if (hard_iface == primary_if) { struct hard_iface *new_if; new_if = hardif_get_active(hard_iface->soft_iface); set_primary_if(bat_priv, new_if); primary_if_select(bat_priv, new_if); if (new_if) hardif_free_ref(new_if); Loading @@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface) hard_iface->soft_iface = NULL; hardif_free_ref(hard_iface); out: if (primary_if) hardif_free_ref(primary_if); } static struct hard_iface *hardif_add_interface(struct net_device *net_dev) Loading Loading @@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this, { struct net_device *net_dev = (struct net_device *)ptr; struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); struct hard_iface *primary_if = NULL; struct bat_priv *bat_priv; if (!hard_iface && event == NETDEV_REGISTER) Loading Loading @@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this, update_mac_addresses(hard_iface); bat_priv = netdev_priv(hard_iface->soft_iface); if (hard_iface == bat_priv->primary_if) update_primary_addr(bat_priv); primary_if = primary_if_get_selected(bat_priv); if (!primary_if) goto hardif_put; if (hard_iface == primary_if) primary_if_update_addr(bat_priv); break; default: break; Loading @@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this, hardif_put: hardif_free_ref(hard_iface); out: if (primary_if) hardif_free_ref(primary_if); return NOTIFY_DONE; } Loading net/batman-adv/hard-interface.h +18 −0 Original line number Diff line number Diff line Loading @@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface) call_rcu(&hard_iface->rcu, hardif_free_rcu); } static inline struct hard_iface *primary_if_get_selected( struct bat_priv *bat_priv) { struct hard_iface *hard_iface; rcu_read_lock(); hard_iface = rcu_dereference(bat_priv->primary_if); if (!hard_iface) goto out; if (!atomic_inc_not_zero(&hard_iface->refcount)) hard_iface = NULL; out: rcu_read_unlock(); return hard_iface; } #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ net/batman-adv/icmp_socket.c +14 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading Loading @@ -233,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, Loading @@ -248,6 +255,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, 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) Loading Loading
net/batman-adv/aggregation.c +0 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, return false; } #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* create a new aggregated packet and add this packet to it */ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, unsigned long send_time, bool direct_link, Loading
net/batman-adv/gateway_client.c +27 −18 Original line number Diff line number Diff line Loading @@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv) return; curr_gw = gw_get_selected_gw_node(bat_priv); if (!curr_gw) if (curr_gw) goto out; rcu_read_lock(); Loading Loading @@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv, struct hlist_node *node; struct gw_node *gw_node, *curr_gw; /** * Note: We don't need a NULL check here, since curr_gw never gets * dereferenced. If curr_gw is NULL we also should not exit as we may * have this gateway in our list (duplication check!) even though we * have no currently selected gateway. */ curr_gw = gw_get_selected_gw_node(bat_priv); if (!curr_gw) goto out; rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { Loading Loading @@ -350,7 +354,7 @@ void gw_node_update(struct bat_priv *bat_priv, gw_deselect(bat_priv); unlock: rcu_read_unlock(); out: if (curr_gw) gw_node_free_ref(curr_gw); } Loading Loading @@ -435,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct hard_iface *primary_if; struct gw_node *gw_node; struct hlist_node *node; int gw_count = 0; int gw_count = 0, ret = 0; if (!bat_priv->primary_if) { return seq_printf(seq, "BATMAN mesh %s disabled - please " primary_if = primary_if_get_selected(bat_priv); if (!primary_if) { ret = seq_printf(seq, "BATMAN mesh %s disabled - please " "specify interfaces to enable it\n", net_dev->name); goto out; } if (bat_priv->primary_if->if_status != IF_ACTIVE) { return seq_printf(seq, "BATMAN mesh %s disabled - " if (primary_if->if_status != IF_ACTIVE) { ret = seq_printf(seq, "BATMAN mesh %s disabled - " "primary interface not active\n", net_dev->name); goto out; } seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", "Gateway", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, bat_priv->primary_if->net_dev->name, bat_priv->primary_if->net_dev->dev_addr, net_dev->name); primary_if->net_dev->name, primary_if->net_dev->dev_addr, net_dev->name); rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { Loading @@ -476,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) if (gw_count == 0) seq_printf(seq, "No gateways in range ...\n"); return 0; out: if (primary_if) hardif_free_ref(primary_if); return ret; } int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) Loading
net/batman-adv/hard-interface.c +57 −26 Original line number Diff line number Diff line Loading @@ -110,47 +110,60 @@ static struct hard_iface *hardif_get_active(struct net_device *soft_iface) return hard_iface; } static void update_primary_addr(struct bat_priv *bat_priv) static void primary_if_update_addr(struct bat_priv *bat_priv) { struct vis_packet *vis_packet; struct hard_iface *primary_if; primary_if = primary_if_get_selected(bat_priv); if (!primary_if) goto out; vis_packet = (struct vis_packet *) bat_priv->my_vis_info->skb_packet->data; memcpy(vis_packet->vis_orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); primary_if->net_dev->dev_addr, ETH_ALEN); out: if (primary_if) hardif_free_ref(primary_if); } static void set_primary_if(struct bat_priv *bat_priv, struct hard_iface *hard_iface) static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *new_hard_iface) { struct hard_iface *curr_hard_iface; struct batman_packet *batman_packet; struct hard_iface *old_if; if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) hard_iface = NULL; spin_lock_bh(&hardif_list_lock); old_if = bat_priv->primary_if; bat_priv->primary_if = hard_iface; if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) new_hard_iface = NULL; if (old_if) hardif_free_ref(old_if); curr_hard_iface = bat_priv->primary_if; rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); if (!bat_priv->primary_if) return; if (curr_hard_iface) hardif_free_ref(curr_hard_iface); batman_packet = (struct batman_packet *)(hard_iface->packet_buff); if (!new_hard_iface) goto out; batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); batman_packet->flags = PRIMARIES_FIRST_HOP; batman_packet->ttl = TTL; update_primary_addr(bat_priv); primary_if_update_addr(bat_priv); /*** * hacky trick to make sure that we send the HNA information via * our new primary interface */ atomic_set(&bat_priv->hna_local_changed, 1); out: spin_unlock_bh(&hardif_list_lock); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) Loading Loading @@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface) static void hardif_activate_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv; struct hard_iface *primary_if = NULL; if (hard_iface->if_status != IF_INACTIVE) return; goto out; bat_priv = netdev_priv(hard_iface->soft_iface); Loading @@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) * the first active interface becomes our primary interface or * the next active interface after the old primay interface was removed */ if (!bat_priv->primary_if) set_primary_if(bat_priv, hard_iface); primary_if = primary_if_get_selected(bat_priv); if (!primary_if) primary_if_select(bat_priv, hard_iface); bat_info(hard_iface->soft_iface, "Interface activated: %s\n", hard_iface->net_dev->name); update_min_mtu(hard_iface->soft_iface); return; out: if (primary_if) hardif_free_ref(primary_if); } static void hardif_deactivate_interface(struct hard_iface *hard_iface) Loading Loading @@ -386,12 +404,13 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) void hardif_disable_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); struct hard_iface *primary_if = NULL; if (hard_iface->if_status == IF_ACTIVE) hardif_deactivate_interface(hard_iface); if (hard_iface->if_status != IF_INACTIVE) return; goto out; bat_info(hard_iface->soft_iface, "Removing interface: %s\n", hard_iface->net_dev->name); Loading @@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface) bat_priv->num_ifaces--; orig_hash_del_if(hard_iface, bat_priv->num_ifaces); if (hard_iface == bat_priv->primary_if) { primary_if = primary_if_get_selected(bat_priv); if (hard_iface == primary_if) { struct hard_iface *new_if; new_if = hardif_get_active(hard_iface->soft_iface); set_primary_if(bat_priv, new_if); primary_if_select(bat_priv, new_if); if (new_if) hardif_free_ref(new_if); Loading @@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface) hard_iface->soft_iface = NULL; hardif_free_ref(hard_iface); out: if (primary_if) hardif_free_ref(primary_if); } static struct hard_iface *hardif_add_interface(struct net_device *net_dev) Loading Loading @@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this, { struct net_device *net_dev = (struct net_device *)ptr; struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); struct hard_iface *primary_if = NULL; struct bat_priv *bat_priv; if (!hard_iface && event == NETDEV_REGISTER) Loading Loading @@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this, update_mac_addresses(hard_iface); bat_priv = netdev_priv(hard_iface->soft_iface); if (hard_iface == bat_priv->primary_if) update_primary_addr(bat_priv); primary_if = primary_if_get_selected(bat_priv); if (!primary_if) goto hardif_put; if (hard_iface == primary_if) primary_if_update_addr(bat_priv); break; default: break; Loading @@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this, hardif_put: hardif_free_ref(hard_iface); out: if (primary_if) hardif_free_ref(primary_if); return NOTIFY_DONE; } Loading
net/batman-adv/hard-interface.h +18 −0 Original line number Diff line number Diff line Loading @@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface) call_rcu(&hard_iface->rcu, hardif_free_rcu); } static inline struct hard_iface *primary_if_get_selected( struct bat_priv *bat_priv) { struct hard_iface *hard_iface; rcu_read_lock(); hard_iface = rcu_dereference(bat_priv->primary_if); if (!hard_iface) goto out; if (!atomic_inc_not_zero(&hard_iface->refcount)) hard_iface = NULL; out: rcu_read_unlock(); return hard_iface; } #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
net/batman-adv/icmp_socket.c +14 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading Loading @@ -233,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, Loading @@ -248,6 +255,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, 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) Loading