The following commit has been merged in the master branch:
commit c83ebbba1d9bc75c2c056a128bea7c030b9f986e
Merge: cbe97119b339d684d2fa12ecd04506dfa07a28ac ccf1183f53baa879cd5a808dbb904f6053fa40f3
Author: Marek Lindner <lindner_marek(a)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;
--
batman-adv