The following commit has been merged in the next branch: commit c83ebbba1d9bc75c2c056a128bea7c030b9f986e Merge: cbe97119b339d684d2fa12ecd04506dfa07a28ac ccf1183f53baa879cd5a808dbb904f6053fa40f3 Author: Marek Lindner lindner_marek@yahoo.de Date: Mon May 14 00:00:28 2012 +0800
Merge branch 'next'
diff --combined routing.c index 9beb2e2,4f2059f..8eec108 --- a/routing.c +++ b/routing.c @@@ -573,7 -573,7 +573,7 @@@ int recv_tt_query(struct sk_buff *skb, { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct tt_query_packet *tt_query; - uint16_t tt_len; + uint16_t tt_size; struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */ @@@ -596,10 -596,10 +596,10 @@@
tt_query = (struct tt_query_packet *)skb->data;
- tt_query->tt_data = ntohs(tt_query->tt_data); - switch (tt_query->flags & TT_QUERY_TYPE_MASK) { case TT_REQUEST: + inc_counter(bat_priv, BAT_CNT_TT_REQUEST_RX); + /* If we cannot provide an answer the tt_request is * forwarded */ if (!send_tt_response(bat_priv, tt_query)) { @@@ -607,23 -607,22 +607,23 @@@ "Routing TT_REQUEST to %pM [%c]\n", tt_query->dst, (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); - tt_query->tt_data = htons(tt_query->tt_data); return route_unicast_packet(skb, recv_if); } break; case TT_RESPONSE: + inc_counter(bat_priv, BAT_CNT_TT_RESPONSE_RX); + if (is_my_mac(tt_query->dst)) { /* packet needs to be linearized to access the TT * changes */ if (skb_linearize(skb) < 0) goto out;
- tt_len = tt_query->tt_data * sizeof(struct tt_change); + tt_size = tt_len(ntohs(tt_query->tt_data));
/* Ensure we have all the claimed data */ if (unlikely(skb_headlen(skb) < - sizeof(struct tt_query_packet) + tt_len)) + sizeof(struct tt_query_packet) + tt_size)) goto out;
handle_tt_response(bat_priv, tt_query); @@@ -632,6 -631,7 +632,6 @@@ "Routing TT_RESPONSE to %pM [%c]\n", tt_query->dst, (tt_query->flags & TT_FULL_TABLE ? 'F' : '.')); - tt_query->tt_data = htons(tt_query->tt_data); return route_unicast_packet(skb, recv_if); } break; @@@ -663,8 -663,6 +663,8 @@@ int recv_roam_adv(struct sk_buff *skb, if (is_broadcast_ether_addr(ethhdr->h_source)) goto out;
+ inc_counter(bat_priv, BAT_CNT_TT_ROAM_ADV_RX); + roam_adv_packet = (struct roam_adv_packet *)skb->data;
if (!is_my_mac(roam_adv_packet->dst)) @@@ -872,10 -870,6 +872,10 @@@ static int route_unicast_packet(struct /* decrement ttl */ unicast_packet->header.ttl--;
+ /* Update stats counter */ + inc_counter(bat_priv, BAT_CNT_FORWARD); + add_counter(bat_priv, BAT_CNT_FORWARD_BYTES, skb->len + ETH_HLEN); + /* route it */ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = NET_RX_SUCCESS; @@@ -928,7 -922,8 +928,8 @@@ static int check_unicast_ttvn(struct ba sizeof(struct unicast_packet));
/* we don't have an updated route for this client, so we should - * not try to reroute the packet!! */ + * not try to reroute the packet!! + */ if (tt_global_client_is_roaming(bat_priv, ethhdr->h_dest)) return 1;
diff --combined translation-table.c index b16fb81,a66c2dc..621e188 --- a/translation-table.c +++ b/translation-table.c @@@ -181,14 -181,14 +181,14 @@@ int tt_len(int changes_num static int tt_local_init(struct bat_priv *bat_priv) { if (bat_priv->tt_local_hash) - return 1; + return 0;
bat_priv->tt_local_hash = hash_new(1024);
if (!bat_priv->tt_local_hash) - return 0; + return -ENOMEM;
- return 1; + return 0; }
void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, @@@ -275,64 -275,14 +275,64 @@@ out tt_global_entry_free_ref(tt_global_entry); }
-int tt_changes_fill_buffer(struct bat_priv *bat_priv, - unsigned char *buff, int buff_len) +static void tt_realloc_packet_buff(unsigned char **packet_buff, + int *packet_buff_len, int min_packet_len, + int new_packet_len) +{ + unsigned char *new_buff; + + new_buff = kmalloc(new_packet_len, GFP_ATOMIC); + + /* keep old buffer if kmalloc should fail */ + if (new_buff) { + memcpy(new_buff, *packet_buff, min_packet_len); + kfree(*packet_buff); + *packet_buff = new_buff; + *packet_buff_len = new_packet_len; + } +} + +static void tt_prepare_packet_buff(struct bat_priv *bat_priv, + unsigned char **packet_buff, + int *packet_buff_len, int min_packet_len) +{ + struct hard_iface *primary_if; + int req_len; + + primary_if = primary_if_get_selected(bat_priv); + + req_len = min_packet_len; + req_len += tt_len(atomic_read(&bat_priv->tt_local_changes)); + + /* if we have too many changes for one packet don't send any + * and wait for the tt table request which will be fragmented + */ + if ((!primary_if) || (req_len > primary_if->soft_iface->mtu)) + req_len = min_packet_len; + + tt_realloc_packet_buff(packet_buff, packet_buff_len, + min_packet_len, req_len); + + if (primary_if) + hardif_free_ref(primary_if); +} + +static int tt_changes_fill_buff(struct bat_priv *bat_priv, + unsigned char **packet_buff, + int *packet_buff_len, int min_packet_len) { - int count = 0, tot_changes = 0; struct tt_change_node *entry, *safe; + int count = 0, tot_changes = 0, new_len; + unsigned char *tt_buff; + + tt_prepare_packet_buff(bat_priv, packet_buff, + packet_buff_len, min_packet_len);
- if (buff_len > 0) - tot_changes = buff_len / tt_len(1); + new_len = *packet_buff_len - min_packet_len; + tt_buff = *packet_buff + min_packet_len; + + if (new_len > 0) + tot_changes = new_len / tt_len(1);
spin_lock_bh(&bat_priv->tt_changes_list_lock); atomic_set(&bat_priv->tt_local_changes, 0); @@@ -340,7 -290,7 +340,7 @@@ list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, list) { if (count < tot_changes) { - memcpy(buff + tt_len(count), + memcpy(tt_buff + tt_len(count), &entry->change, sizeof(struct tt_change)); count++; } @@@ -354,20 -304,22 +354,20 @@@ kfree(bat_priv->tt_buff); bat_priv->tt_buff_len = 0; bat_priv->tt_buff = NULL; - /* We check whether this new OGM has no changes due to size - * problems */ - if (buff_len > 0) { - /** - * if kmalloc() fails we will reply with the full table + /* check whether this new OGM has no changes due to size problems */ + if (new_len > 0) { + /* if kmalloc() fails we will reply with the full table * instead of providing the diff */ - bat_priv->tt_buff = kmalloc(buff_len, GFP_ATOMIC); + bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC); if (bat_priv->tt_buff) { - memcpy(bat_priv->tt_buff, buff, buff_len); - bat_priv->tt_buff_len = buff_len; + memcpy(bat_priv->tt_buff, tt_buff, new_len); + bat_priv->tt_buff_len = new_len; } } spin_unlock_bh(&bat_priv->tt_buff_lock);
- return tot_changes; + return count; }
int tt_local_seq_print_text(struct seq_file *seq, void *offset) @@@ -539,14 -491,14 +539,14 @@@ static void tt_local_table_free(struct static int tt_global_init(struct bat_priv *bat_priv) { if (bat_priv->tt_global_hash) - return 1; + return 0;
bat_priv->tt_global_hash = hash_new(1024);
if (!bat_priv->tt_global_hash) - return 0; + return -ENOMEM;
- return 1; + return 0; }
static void tt_changes_list_free(struct bat_priv *bat_priv) @@@ -1404,8 -1356,6 +1404,8 @@@ static int send_tt_request(struct bat_p dst_orig_node->orig, neigh_node->addr, (full_table ? 'F' : '.'));
+ inc_counter(bat_priv, BAT_CNT_TT_REQUEST_TX); + send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = 0;
@@@ -1466,7 -1416,7 +1466,7 @@@ static bool send_other_tt_response(stru
/* I don't have the requested data */ if (orig_ttvn != req_ttvn || - tt_request->tt_data != req_dst_orig_node->tt_crc) + tt_request->tt_data != htons(req_dst_orig_node->tt_crc)) goto out;
/* If the full table has been explicitly requested */ @@@ -1530,8 -1480,6 +1530,8 @@@ res_dst_orig_node->orig, neigh_node->addr, req_dst_orig_node->orig, req_ttvn);
+ inc_counter(bat_priv, BAT_CNT_TT_RESPONSE_TX); + send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = true; goto out; @@@ -1648,8 -1596,6 +1648,8 @@@ static bool send_my_tt_response(struct orig_node->orig, neigh_node->addr, (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
+ inc_counter(bat_priv, BAT_CNT_TT_RESPONSE_TX); + send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = true; goto out; @@@ -1726,7 -1672,7 +1726,7 @@@ static void tt_fill_gtable(struct bat_p
_tt_update_changes(bat_priv, orig_node, (struct tt_change *)(tt_response + 1), - tt_response->tt_data, tt_response->ttvn); + ntohs(tt_response->tt_data), tt_response->ttvn);
spin_lock_bh(&orig_node->tt_buff_lock); kfree(orig_node->tt_buff); @@@ -1781,8 -1727,7 +1781,8 @@@ void handle_tt_response(struct bat_pri
bat_dbg(DBG_TT, bat_priv, "Received TT_RESPONSE from %pM for ttvn %d t_size: %d [%c]\n", - tt_response->src, tt_response->ttvn, tt_response->tt_data, + tt_response->src, tt_response->ttvn, + ntohs(tt_response->tt_data), (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
/* we should have never asked a backbone gw */ @@@ -1796,8 -1741,7 +1796,8 @@@ if (tt_response->flags & TT_FULL_TABLE) tt_fill_gtable(bat_priv, tt_response); else - tt_update_changes(bat_priv, orig_node, tt_response->tt_data, + tt_update_changes(bat_priv, orig_node, + ntohs(tt_response->tt_data), tt_response->ttvn, (struct tt_change *)(tt_response + 1));
@@@ -1823,15 -1767,11 +1823,15 @@@ out
int tt_init(struct bat_priv *bat_priv) { - if (!tt_local_init(bat_priv)) - return 0; + int ret;
- if (!tt_global_init(bat_priv)) - return 0; + ret = tt_local_init(bat_priv); + if (ret < 0) + return ret; + + ret = tt_global_init(bat_priv); + if (ret < 0) + return ret;
tt_start_timer(bat_priv);
@@@ -1955,8 -1895,6 +1955,8 @@@ static void send_roam_adv(struct bat_pr "Sending ROAMING_ADV to %pM (client %pM) via %pM\n", orig_node->orig, client, neigh_node->addr);
+ inc_counter(bat_priv, BAT_CNT_TT_ROAM_ADV_TX); + send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = 0;
@@@ -2073,56 -2011,20 +2073,56 @@@ static void tt_local_purge_pending_clie
}
-void tt_commit_changes(struct bat_priv *bat_priv) +static int tt_commit_changes(struct bat_priv *bat_priv, + unsigned char **packet_buff, int *packet_buff_len, + int packet_min_len) { - uint16_t changed_num = tt_set_flags(bat_priv->tt_local_hash, - TT_CLIENT_NEW, false); - /* all the reset entries have now to be effectively counted as local - * entries */ + uint16_t changed_num = 0; + + if (atomic_read(&bat_priv->tt_local_changes) < 1) + return -ENOENT; + + changed_num = tt_set_flags(bat_priv->tt_local_hash, + TT_CLIENT_NEW, false); + + /* all reset entries have to be counted as local entries */ atomic_add(changed_num, &bat_priv->num_local_tt); tt_local_purge_pending_clients(bat_priv); + bat_priv->tt_crc = tt_local_crc(bat_priv);
/* Increment the TTVN only once per OGM interval */ atomic_inc(&bat_priv->ttvn); bat_dbg(DBG_TT, bat_priv, "Local changes committed, updating to ttvn %u\n", (uint8_t)atomic_read(&bat_priv->ttvn)); bat_priv->tt_poss_change = false; + + /* reset the sending counter */ + atomic_set(&bat_priv->tt_ogm_append_cnt, TT_OGM_APPEND_MAX); + + return tt_changes_fill_buff(bat_priv, packet_buff, + packet_buff_len, packet_min_len); +} + +/* when calling this function (hard_iface == primary_if) has to be true */ +int batadv_tt_append_diff(struct bat_priv *bat_priv, + unsigned char **packet_buff, int *packet_buff_len, + int packet_min_len) +{ + int tt_num_changes; + + /* if at least one change happened */ + tt_num_changes = tt_commit_changes(bat_priv, packet_buff, + packet_buff_len, packet_min_len); + + /* if the changes have been sent often enough */ + if ((tt_num_changes < 0) && + (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) { + tt_realloc_packet_buff(packet_buff, packet_buff_len, + packet_min_len, packet_min_len); + tt_num_changes = 0; + } + + return tt_num_changes; }
bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) @@@ -2220,7 -2122,8 +2220,8 @@@ request_table
/* returns true whether we know that the client has moved from its old * originator to another one. This entry is kept is still kept for consistency - * purposes */ + * purposes + */ bool tt_global_client_is_roaming(struct bat_priv *bat_priv, uint8_t *addr) { struct tt_global_entry *tt_global_entry;