diff options
Diffstat (limited to 'kernel/net/batman-adv/network-coding.c')
-rw-r--r-- | kernel/net/batman-adv/network-coding.c | 134 |
1 files changed, 79 insertions, 55 deletions
diff --git a/kernel/net/batman-adv/network-coding.c b/kernel/net/batman-adv/network-coding.c index 127cc4d73..d0956f726 100644 --- a/kernel/net/batman-adv/network-coding.c +++ b/kernel/net/batman-adv/network-coding.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2014 B.A.T.M.A.N. contributors: +/* Copyright (C) 2012-2015 B.A.T.M.A.N. contributors: * * Martin Hundebøll, Jeppe Ledet-Pedersen * @@ -15,15 +15,45 @@ * along with this program; if not, see <http://www.gnu.org/licenses/>. */ +#include "network-coding.h" +#include "main.h" + +#include <linux/atomic.h> +#include <linux/bitops.h> +#include <linux/byteorder/generic.h> +#include <linux/compiler.h> #include <linux/debugfs.h> +#include <linux/errno.h> +#include <linux/etherdevice.h> +#include <linux/fs.h> +#include <linux/if_ether.h> +#include <linux/if_packet.h> +#include <linux/init.h> +#include <linux/jhash.h> +#include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/lockdep.h> +#include <linux/netdevice.h> +#include <linux/printk.h> +#include <linux/random.h> +#include <linux/rculist.h> +#include <linux/rcupdate.h> +#include <linux/seq_file.h> +#include <linux/skbuff.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/stat.h> +#include <linux/stddef.h> +#include <linux/string.h> +#include <linux/workqueue.h> -#include "main.h" +#include "hard-interface.h" #include "hash.h" -#include "network-coding.h" -#include "send.h" #include "originator.h" -#include "hard-interface.h" +#include "packet.h" #include "routing.h" +#include "send.h" static struct lock_class_key batadv_nc_coding_hash_lock_class_key; static struct lock_class_key batadv_nc_decoding_hash_lock_class_key; @@ -100,14 +130,13 @@ void batadv_nc_status_update(struct net_device *net_dev) */ static void batadv_nc_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, struct batadv_orig_node *orig, - uint8_t flags, - void *tvlv_value, - uint16_t tvlv_value_len) + u8 flags, + void *tvlv_value, u16 tvlv_value_len) { if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) - orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_NC; + clear_bit(BATADV_ORIG_CAPA_HAS_NC, &orig->capabilities); else - orig->capabilities |= BATADV_ORIG_CAPA_HAS_NC; + set_bit(BATADV_ORIG_CAPA_HAS_NC, &orig->capabilities); } /** @@ -155,7 +184,7 @@ err: */ void batadv_nc_init_bat_priv(struct batadv_priv *bat_priv) { - atomic_set(&bat_priv->network_coding, 1); + atomic_set(&bat_priv->network_coding, 0); bat_priv->nc.min_tq = 200; bat_priv->nc.max_fwd_delay = 10; bat_priv->nc.max_buffer_time = 200; @@ -174,28 +203,25 @@ void batadv_nc_init_orig(struct batadv_orig_node *orig_node) } /** - * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove - * its refcount on the orig_node - * @rcu: rcu pointer of the nc node + * batadv_nc_node_release - release nc_node from lists and queue for free after + * rcu grace period + * @nc_node: the nc node to free */ -static void batadv_nc_node_free_rcu(struct rcu_head *rcu) +static void batadv_nc_node_release(struct batadv_nc_node *nc_node) { - struct batadv_nc_node *nc_node; - - nc_node = container_of(rcu, struct batadv_nc_node, rcu); batadv_orig_node_free_ref(nc_node->orig_node); - kfree(nc_node); + kfree_rcu(nc_node, rcu); } /** - * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly - * frees it + * batadv_nc_node_free_ref - decrement the nc node refcounter and possibly + * release it * @nc_node: the nc node to free */ static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) { if (atomic_dec_and_test(&nc_node->refcount)) - call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu); + batadv_nc_node_release(nc_node); } /** @@ -275,7 +301,7 @@ static bool batadv_nc_to_purge_nc_path_decoding(struct batadv_priv *bat_priv, * max_buffer time */ return batadv_has_timed_out(nc_path->last_valid, - bat_priv->nc.max_buffer_time*10); + bat_priv->nc.max_buffer_time * 10); } /** @@ -352,7 +378,7 @@ static void batadv_nc_purge_orig_hash(struct batadv_priv *bat_priv) struct batadv_hashtable *hash = bat_priv->orig_hash; struct hlist_head *head; struct batadv_orig_node *orig_node; - uint32_t i; + u32 i; if (!hash) return; @@ -388,7 +414,7 @@ static void batadv_nc_purge_paths(struct batadv_priv *bat_priv, struct hlist_node *node_tmp; struct batadv_nc_path *nc_path; spinlock_t *lock; /* Protects lists in hash */ - uint32_t i; + u32 i; for (i = 0; i < hash->size; i++) { head = &hash->table[i]; @@ -448,19 +474,13 @@ static void batadv_nc_hash_key_gen(struct batadv_nc_path *key, const char *src, * * Returns the selected index in the hash table for the given data. */ -static uint32_t batadv_nc_hash_choose(const void *data, uint32_t size) +static u32 batadv_nc_hash_choose(const void *data, u32 size) { const struct batadv_nc_path *nc_path = data; - uint32_t hash = 0; - - hash = batadv_hash_bytes(hash, &nc_path->prev_hop, - sizeof(nc_path->prev_hop)); - hash = batadv_hash_bytes(hash, &nc_path->next_hop, - sizeof(nc_path->next_hop)); + u32 hash = 0; - hash += (hash << 3); - hash ^= (hash >> 11); - hash += (hash << 15); + hash = jhash(&nc_path->prev_hop, sizeof(nc_path->prev_hop), hash); + hash = jhash(&nc_path->next_hop, sizeof(nc_path->next_hop), hash); return hash % size; } @@ -563,6 +583,8 @@ static bool batadv_nc_sniffed_purge(struct batadv_priv *bat_priv, unsigned long timeout = bat_priv->nc.max_buffer_time; bool res = false; + lockdep_assert_held(&nc_path->packet_list_lock); + /* Packets are added to tail, so the remaining packets did not time * out and we can stop processing the current queue */ @@ -599,6 +621,8 @@ static bool batadv_nc_fwd_flush(struct batadv_priv *bat_priv, { unsigned long timeout = bat_priv->nc.max_fwd_delay; + lockdep_assert_held(&nc_path->packet_list_lock); + /* Packets are added to tail, so the remaining packets did not time * out and we can stop processing the current queue */ @@ -720,8 +744,8 @@ static bool batadv_can_nc_with_orig(struct batadv_priv *bat_priv, struct batadv_ogm_packet *ogm_packet) { struct batadv_orig_ifinfo *orig_ifinfo; - uint32_t last_real_seqno; - uint8_t last_ttl; + u32 last_real_seqno; + u8 last_ttl; orig_ifinfo = batadv_orig_ifinfo_get(orig_node, BATADV_IF_DEFAULT); if (!orig_ifinfo) @@ -849,8 +873,8 @@ free: } /** - * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node structs - * (best called on incoming OGMs) + * batadv_nc_update_nc_node - updates stored incoming and outgoing nc node + * structs (best called on incoming OGMs) * @bat_priv: the bat priv with all the soft interface information * @orig_node: orig node originating the ogm packet * @orig_neigh_node: neighboring orig node from which we received the ogm packet @@ -864,14 +888,15 @@ void batadv_nc_update_nc_node(struct batadv_priv *bat_priv, struct batadv_ogm_packet *ogm_packet, int is_single_hop_neigh) { - struct batadv_nc_node *in_nc_node = NULL, *out_nc_node = NULL; + struct batadv_nc_node *in_nc_node = NULL; + struct batadv_nc_node *out_nc_node = NULL; /* Check if network coding is enabled */ if (!atomic_read(&bat_priv->network_coding)) goto out; /* check if orig node is network coding enabled */ - if (!(orig_node->capabilities & BATADV_ORIG_CAPA_HAS_NC)) + if (!test_bit(BATADV_ORIG_CAPA_HAS_NC, &orig_node->capabilities)) goto out; /* accept ogms from 'good' neighbors and single hop neighbors */ @@ -914,8 +939,8 @@ out: */ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, struct batadv_hashtable *hash, - uint8_t *src, - uint8_t *dst) + u8 *src, + u8 *dst) { int hash_added; struct batadv_nc_path *nc_path, nc_path_key; @@ -967,9 +992,9 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, * selection of a receiver with slightly lower TQ than the other * @tq: to be weighted tq value */ -static uint8_t batadv_nc_random_weight_tq(uint8_t tq) +static u8 batadv_nc_random_weight_tq(u8 tq) { - uint8_t rand_val, rand_tq; + u8 rand_val, rand_tq; get_random_bytes(&rand_val, sizeof(rand_val)); @@ -1014,7 +1039,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, struct batadv_nc_packet *nc_packet, struct batadv_neigh_node *neigh_node) { - uint8_t tq_weighted_neigh, tq_weighted_coding, tq_tmp; + u8 tq_weighted_neigh, tq_weighted_coding, tq_tmp; struct sk_buff *skb_dest, *skb_src; struct batadv_unicast_packet *packet1; struct batadv_unicast_packet *packet2; @@ -1023,7 +1048,7 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, struct batadv_neigh_node *router_coding = NULL; struct batadv_neigh_ifinfo *router_neigh_ifinfo = NULL; struct batadv_neigh_ifinfo *router_coding_ifinfo = NULL; - uint8_t *first_source, *first_dest, *second_source, *second_dest; + u8 *first_source, *first_dest, *second_source, *second_dest; __be32 packet_id1, packet_id2; size_t count; bool res = false; @@ -1207,8 +1232,7 @@ out: * * Returns true if coding of a decoded packet is allowed. */ -static bool batadv_nc_skb_coding_possible(struct sk_buff *skb, - uint8_t *dst, uint8_t *src) +static bool batadv_nc_skb_coding_possible(struct sk_buff *skb, u8 *dst, u8 *src) { if (BATADV_SKB_CB(skb)->decoded && !batadv_compare_eth(dst, src)) return false; @@ -1231,7 +1255,7 @@ batadv_nc_path_search(struct batadv_priv *bat_priv, struct batadv_nc_node *in_nc_node, struct batadv_nc_node *out_nc_node, struct sk_buff *skb, - uint8_t *eth_dst) + u8 *eth_dst) { struct batadv_nc_path *nc_path, nc_path_key; struct batadv_nc_packet *nc_packet_out = NULL; @@ -1297,8 +1321,8 @@ batadv_nc_path_search(struct batadv_priv *bat_priv, static struct batadv_nc_packet * batadv_nc_skb_src_search(struct batadv_priv *bat_priv, struct sk_buff *skb, - uint8_t *eth_dst, - uint8_t *eth_src, + u8 *eth_dst, + u8 *eth_src, struct batadv_nc_node *in_nc_node) { struct batadv_orig_node *orig_node; @@ -1338,7 +1362,7 @@ batadv_nc_skb_src_search(struct batadv_priv *bat_priv, */ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, struct sk_buff *skb, - uint8_t *eth_dst_new) + u8 *eth_dst_new) { struct ethhdr *ethhdr; @@ -1614,7 +1638,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, struct batadv_unicast_packet *unicast_packet; struct batadv_coded_packet coded_packet_tmp; struct ethhdr *ethhdr, ethhdr_tmp; - uint8_t *orig_dest, ttl, ttvn; + u8 *orig_dest, ttl, ttvn; unsigned int coding_len; int err; @@ -1706,7 +1730,7 @@ batadv_nc_find_decoding_packet(struct batadv_priv *bat_priv, struct batadv_hashtable *hash = bat_priv->nc.decoding_hash; struct batadv_nc_packet *tmp_nc_packet, *nc_packet = NULL; struct batadv_nc_path *nc_path, nc_path_key; - uint8_t *dest, *source; + u8 *dest, *source; __be32 packet_id; int index; |