* [PATCH 13/16] batman-adv: remove useless find_router look up
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Simon Wunderlich, Marek Lindner,
Antonio Quartulli
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Simon Wunderlich <simon@open-mesh.com>
This is not used anymore with the new fragmentation, and it might
actually mess up the bonding code because find_router() assumes it
is only called once per packet.
Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/send.c | 29 ++++++++---------------------
1 file changed, 8 insertions(+), 21 deletions(-)
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 4bbcf51..82588e4 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -250,30 +250,19 @@ int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct batadv_unicast_packet *unicast_packet;
struct batadv_orig_node *orig_node;
- struct batadv_neigh_node *neigh_node;
int ret = NET_RX_DROP;
/* get routing information */
- if (is_multicast_ether_addr(ethhdr->h_dest)) {
+ if (is_multicast_ether_addr(ethhdr->h_dest))
orig_node = batadv_gw_get_selected_orig(bat_priv);
- if (orig_node)
- goto find_router;
- }
+ else
+ /* check for tt host - increases orig_node refcount.
+ * returns NULL in case of AP isolation
+ */
+ orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
+ ethhdr->h_dest);
- /* check for tt host - increases orig_node refcount.
- * returns NULL in case of AP isolation
- */
- orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
- ethhdr->h_dest);
-
-find_router:
- /* find_router():
- * - if orig_node is NULL it returns NULL
- * - increases neigh_nodes refcount if found.
- */
- neigh_node = batadv_find_router(bat_priv, orig_node, NULL);
-
- if (!neigh_node)
+ if (!orig_node)
goto out;
switch (packet_type) {
@@ -305,8 +294,6 @@ find_router:
ret = 0;
out:
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
if (ret == NET_RX_DROP)
--
1.8.3.2
^ permalink raw reply related
* [PATCH v2 net-next] fib_trie: remove duplicated rcu lock
From: baker.kernel @ 2013-10-13 11:50 UTC (permalink / raw)
To: davem, eric.dumazet
Cc: kuznet, jmorris, yoshfuji, kaber, netdev, linux-kernel,
baker.zhang
In-Reply-To: <1381636737.3392.29.camel@edumazet-glaptop.roam.corp.google.com>
From: "baker.zhang" <baker.kernel@gmail.com>
fib_table_lookup has included the rcu lock protection.
Signed-off-by: baker.zhang <baker.kernel@gmail.com>
---
Thanks for Eric Dumazet's review.
The V1 patch remove a necessary rcu read lock.
net/ipv4/fib_frontend.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index b3f627a..d846304 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -933,7 +933,6 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
local_bh_disable();
frn->tb_id = tb->tb_id;
- rcu_read_lock();
frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
if (!frn->err) {
@@ -942,7 +941,6 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
frn->type = res.type;
frn->scope = res.scope;
}
- rcu_read_unlock();
local_bh_enable();
}
}
--
1.8.1.2
^ permalink raw reply related
* [PATCH 11/16] batman-adv: create common header for ICMP packets
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <antonio@open-mesh.com>
the icmp and the icmp_rr packets share the same initial
fields since they use the same code to be processed and
forwarded.
Extract the common fields and put them into a separate
struct so that future ICMP packets can be easily added
without bloating the packet definition.
However, keep the seqno field outside of the newly created
common header because future ICMP types may require a
bigger sequence number space.
This change breaks compatibility due to fields reordering
in the ICMP headers.
Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/icmp_socket.c | 22 ++++++++++-----------
net/batman-adv/main.c | 4 ++--
net/batman-adv/packet.h | 46 ++++++++++++++++++++++++++++++--------------
net/batman-adv/routing.c | 40 ++++++++++++++++++++------------------
4 files changed, 66 insertions(+), 46 deletions(-)
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index 5a99bb4..82ac647 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -192,25 +192,25 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
goto free_skb;
}
- if (icmp_packet->header.packet_type != BATADV_ICMP) {
+ if (icmp_packet->icmph.header.packet_type != BATADV_ICMP) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
len = -EINVAL;
goto free_skb;
}
- if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
+ if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
len = -EINVAL;
goto free_skb;
}
- icmp_packet->uid = socket_client->index;
+ icmp_packet->icmph.uid = socket_client->index;
- if (icmp_packet->header.version != BATADV_COMPAT_VERSION) {
- icmp_packet->msg_type = BATADV_PARAMETER_PROBLEM;
- icmp_packet->header.version = BATADV_COMPAT_VERSION;
+ if (icmp_packet->icmph.header.version != BATADV_COMPAT_VERSION) {
+ icmp_packet->icmph.msg_type = BATADV_PARAMETER_PROBLEM;
+ icmp_packet->icmph.header.version = BATADV_COMPAT_VERSION;
batadv_socket_add_packet(socket_client, icmp_packet,
packet_len);
goto free_skb;
@@ -219,7 +219,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto dst_unreach;
- orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->dst);
+ orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.dst);
if (!orig_node)
goto dst_unreach;
@@ -233,7 +233,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
if (neigh_node->if_incoming->if_status != BATADV_IF_ACTIVE)
goto dst_unreach;
- memcpy(icmp_packet->orig,
+ memcpy(icmp_packet->icmph.orig,
primary_if->net_dev->dev_addr, ETH_ALEN);
if (packet_len == sizeof(struct batadv_icmp_packet_rr))
@@ -244,7 +244,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
goto out;
dst_unreach:
- icmp_packet->msg_type = BATADV_DESTINATION_UNREACHABLE;
+ icmp_packet->icmph.msg_type = BATADV_DESTINATION_UNREACHABLE;
batadv_socket_add_packet(socket_client, icmp_packet, packet_len);
free_skb:
kfree_skb(skb);
@@ -318,7 +318,7 @@ static void batadv_socket_add_packet(struct batadv_socket_client *socket_client,
/* while waiting for the lock the socket_client could have been
* deleted
*/
- if (!batadv_socket_client_hash[icmp_packet->uid]) {
+ if (!batadv_socket_client_hash[icmp_packet->icmph.uid]) {
spin_unlock_bh(&socket_client->lock);
kfree(socket_packet);
return;
@@ -347,7 +347,7 @@ void batadv_socket_receive_packet(struct batadv_icmp_packet_rr *icmp_packet,
{
struct batadv_socket_client *hash;
- hash = batadv_socket_client_hash[icmp_packet->uid];
+ hash = batadv_socket_client_hash[icmp_packet->icmph.uid];
if (hash)
batadv_socket_add_packet(hash, icmp_packet, icmp_len);
}
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index ca6f134..519138e 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -401,8 +401,8 @@ static void batadv_recv_handler_init(void)
BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
- BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
- BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, icmph.dst) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, icmph.dst) != 4);
/* broadcast packet */
batadv_rx_handler[BATADV_BCAST] = batadv_recv_bcast_packet;
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index aa46c27..65e723e 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -186,29 +186,47 @@ struct batadv_ogm_packet {
#define BATADV_OGM_HLEN sizeof(struct batadv_ogm_packet)
+/**
+ * batadv_icmp_header - common ICMP header
+ * @header: common batman header
+ * @msg_type: ICMP packet type
+ * @dst: address of the destination node
+ * @orig: address of the source node
+ * @uid: local ICMP socket identifier
+ */
+struct batadv_icmp_header {
+ struct batadv_header header;
+ uint8_t msg_type; /* see ICMP message types above */
+ uint8_t dst[ETH_ALEN];
+ uint8_t orig[ETH_ALEN];
+ uint8_t uid;
+};
+
+/**
+ * batadv_icmp_packet - ICMP packet
+ * @icmph: common ICMP header
+ * @reserved: not used - useful for alignment
+ * @seqno: ICMP sequence number
+ */
struct batadv_icmp_packet {
- struct batadv_header header;
- uint8_t msg_type; /* see ICMP message types above */
- uint8_t dst[ETH_ALEN];
- uint8_t orig[ETH_ALEN];
- __be16 seqno;
- uint8_t uid;
+ struct batadv_icmp_header icmph;
uint8_t reserved;
+ __be16 seqno;
};
#define BATADV_RR_LEN 16
-/* icmp_packet_rr must start with all fields from imcp_packet
- * as this is assumed by code that handles ICMP packets
+/**
+ * batadv_icmp_packet_rr - ICMP RouteRecord packet
+ * @icmph: common ICMP header
+ * @rr_cur: number of entries the rr array
+ * @seqno: ICMP sequence number
+ * @rr: route record array
*/
struct batadv_icmp_packet_rr {
- struct batadv_header header;
- uint8_t msg_type; /* see ICMP message types above */
- uint8_t dst[ETH_ALEN];
- uint8_t orig[ETH_ALEN];
- __be16 seqno;
- uint8_t uid;
+ struct batadv_icmp_header icmph;
uint8_t rr_cur;
+ __be16 seqno;
uint8_t rr[BATADV_RR_LEN][ETH_ALEN];
};
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index a080f63..3281a50 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -258,7 +258,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
/* add data to device queue */
- if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
+ if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
batadv_socket_receive_packet(icmp_packet, icmp_len);
goto out;
}
@@ -269,7 +269,7 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
/* answer echo request (ping) */
/* get routing information */
- orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
+ orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
if (!orig_node)
goto out;
@@ -279,10 +279,11 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
- memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
- icmp_packet->msg_type = BATADV_ECHO_REPLY;
- icmp_packet->header.ttl = BATADV_TTL;
+ memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
+ memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+ ETH_ALEN);
+ icmp_packet->icmph.msg_type = BATADV_ECHO_REPLY;
+ icmp_packet->icmph.header.ttl = BATADV_TTL;
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = NET_RX_SUCCESS;
@@ -306,9 +307,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet = (struct batadv_icmp_packet *)skb->data;
/* send TTL exceeded if packet is an echo request (traceroute) */
- if (icmp_packet->msg_type != BATADV_ECHO_REQUEST) {
+ if (icmp_packet->icmph.msg_type != BATADV_ECHO_REQUEST) {
pr_debug("Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
- icmp_packet->orig, icmp_packet->dst);
+ icmp_packet->icmph.orig, icmp_packet->icmph.dst);
goto out;
}
@@ -317,7 +318,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
goto out;
/* get routing information */
- orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->orig);
+ orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.orig);
if (!orig_node)
goto out;
@@ -327,10 +328,11 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet = (struct batadv_icmp_packet *)skb->data;
- memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
- icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
- icmp_packet->header.ttl = BATADV_TTL;
+ memcpy(icmp_packet->icmph.dst, icmp_packet->icmph.orig, ETH_ALEN);
+ memcpy(icmp_packet->icmph.orig, primary_if->net_dev->dev_addr,
+ ETH_ALEN);
+ icmp_packet->icmph.msg_type = BATADV_TTL_EXCEEDED;
+ icmp_packet->icmph.header.ttl = BATADV_TTL;
if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
ret = NET_RX_SUCCESS;
@@ -379,8 +381,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
/* add record route information if not full */
- if ((icmp_packet->msg_type == BATADV_ECHO_REPLY ||
- icmp_packet->msg_type == BATADV_ECHO_REQUEST) &&
+ if ((icmp_packet->icmph.msg_type == BATADV_ECHO_REPLY ||
+ icmp_packet->icmph.msg_type == BATADV_ECHO_REQUEST) &&
(hdr_size == sizeof(struct batadv_icmp_packet_rr)) &&
(icmp_packet->rr_cur < BATADV_RR_LEN)) {
memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
@@ -389,15 +391,15 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
}
/* packet for me */
- if (batadv_is_my_mac(bat_priv, icmp_packet->dst))
+ if (batadv_is_my_mac(bat_priv, icmp_packet->icmph.dst))
return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size);
/* TTL exceeded */
- if (icmp_packet->header.ttl < 2)
+ if (icmp_packet->icmph.header.ttl < 2)
return batadv_recv_icmp_ttl_exceeded(bat_priv, skb);
/* get routing information */
- orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->dst);
+ orig_node = batadv_orig_hash_find(bat_priv, icmp_packet->icmph.dst);
if (!orig_node)
goto out;
@@ -408,7 +410,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
/* decrement ttl */
- icmp_packet->header.ttl--;
+ icmp_packet->icmph.header.ttl--;
/* route it */
if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
--
1.8.3.2
^ permalink raw reply related
* [PATCH 12/16] batman-adv: consider network coding overhead when calculating required mtu
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Marek Lindner, Antonio Quartulli
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Marek Lindner <lindner_marek@yahoo.de>
The module prints a warning when the MTU on the hard interface is too
small to transfer payload traffic without fragmentation. The required
MTU is calculated based on the encapsulation header size. If network
coding is compild into the module its header size is taken into
account as well.
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/hard-interface.c | 19 ++++++++++---------
net/batman-adv/main.c | 25 +++++++++++++++++++++++++
net/batman-adv/main.h | 1 +
net/batman-adv/soft-interface.c | 2 +-
net/batman-adv/types.h | 7 -------
5 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 004017c..d564af2 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -269,9 +269,10 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
const struct batadv_priv *bat_priv = netdev_priv(soft_iface);
const struct batadv_hard_iface *hard_iface;
/* allow big frames if all devices are capable to do so
- * (have MTU > 1500 + BAT_HEADER_LEN)
+ * (have MTU > 1500 + batadv_max_header_len())
*/
int min_mtu = ETH_DATA_LEN;
+ int max_header_len = batadv_max_header_len();
if (atomic_read(&bat_priv->fragmentation))
goto out;
@@ -285,8 +286,7 @@ int batadv_hardif_min_mtu(struct net_device *soft_iface)
if (hard_iface->soft_iface != soft_iface)
continue;
- min_mtu = min_t(int,
- hard_iface->net_dev->mtu - BATADV_HEADER_LEN,
+ min_mtu = min_t(int, hard_iface->net_dev->mtu - max_header_len,
min_mtu);
}
rcu_read_unlock();
@@ -380,6 +380,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
struct batadv_priv *bat_priv;
struct net_device *soft_iface, *master;
__be16 ethertype = htons(ETH_P_BATMAN);
+ int max_header_len = batadv_max_header_len();
int ret;
if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
@@ -448,18 +449,18 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
hard_iface->net_dev->name);
if (atomic_read(&bat_priv->fragmentation) &&
- hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN)
+ hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
batadv_info(hard_iface->soft_iface,
- "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %zi would solve the problem.\n",
+ "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %i would solve the problem.\n",
hard_iface->net_dev->name, hard_iface->net_dev->mtu,
- ETH_DATA_LEN + BATADV_HEADER_LEN);
+ ETH_DATA_LEN + max_header_len);
if (!atomic_read(&bat_priv->fragmentation) &&
- hard_iface->net_dev->mtu < ETH_DATA_LEN + BATADV_HEADER_LEN)
+ hard_iface->net_dev->mtu < ETH_DATA_LEN + max_header_len)
batadv_info(hard_iface->soft_iface,
- "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %zi.\n",
+ "The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %i.\n",
hard_iface->net_dev->name, hard_iface->net_dev->mtu,
- ETH_DATA_LEN + BATADV_HEADER_LEN);
+ ETH_DATA_LEN + max_header_len);
if (batadv_hardif_is_iface_up(hard_iface))
batadv_hardif_activate_interface(hard_iface);
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 519138e..7f3a5c4 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -256,6 +256,31 @@ out:
}
/**
+ * batadv_max_header_len - calculate maximum encapsulation overhead for a
+ * payload packet
+ *
+ * Return the maximum encapsulation overhead in bytes.
+ */
+int batadv_max_header_len(void)
+{
+ int header_len = 0;
+
+ header_len = max_t(int, header_len,
+ sizeof(struct batadv_unicast_packet));
+ header_len = max_t(int, header_len,
+ sizeof(struct batadv_unicast_4addr_packet));
+ header_len = max_t(int, header_len,
+ sizeof(struct batadv_bcast_packet));
+
+#ifdef CONFIG_BATMAN_ADV_NC
+ header_len = max_t(int, header_len,
+ sizeof(struct batadv_coded_packet));
+#endif
+
+ return header_len;
+}
+
+/**
* batadv_skb_set_priority - sets skb priority according to packet content
* @skb: the packet to be sent
* @offset: offset to the packet content
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 6a74a42..54c13d5 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -191,6 +191,7 @@ void batadv_mesh_free(struct net_device *soft_iface);
int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr);
struct batadv_hard_iface *
batadv_seq_print_text_primary_if_get(struct seq_file *seq);
+int batadv_max_header_len(void);
void batadv_skb_set_priority(struct sk_buff *skb, int offset);
int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype,
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 87e7e4e..15c7237 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -626,7 +626,7 @@ static void batadv_softif_init_early(struct net_device *dev)
*/
dev->mtu = ETH_DATA_LEN;
/* reserve more space in the skbuff for our header */
- dev->hard_header_len = BATADV_HEADER_LEN;
+ dev->hard_header_len = batadv_max_header_len();
/* generate random address */
eth_hw_addr_random(dev);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index d517d5d..5cbb0d0 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -24,13 +24,6 @@
#include "bitarray.h"
#include <linux/kernel.h>
-/**
- * Maximum overhead for the encapsulation for a payload packet
- */
-#define BATADV_HEADER_LEN \
- (ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
- sizeof(struct batadv_bcast_packet)))
-
#ifdef CONFIG_BATMAN_ADV_DAT
/* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed,
--
1.8.3.2
^ permalink raw reply related
* [PATCH 15/16] batman-adv: make batadv_tt_save_orig_buffer() generic
From: Antonio Quartulli @ 2013-10-13 11:23 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <antonio@open-mesh.com>
This is a simple batadv_tt_save_orig_buffer() refactoring
aiming to make it more generic and avoid useless casts.
Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/translation-table.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 58636a7..b521afb 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1496,11 +1496,9 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv)
static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
- const unsigned char *tt_buff,
- uint16_t tt_num_changes)
+ const void *tt_buff,
+ uint16_t tt_buff_len)
{
- uint16_t tt_buff_len = batadv_tt_len(tt_num_changes);
-
/* Replace the old buffer only if I received something in the
* last OGM (the OGM could carry no changes)
*/
@@ -2037,8 +2035,8 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
_batadv_tt_update_changes(bat_priv, orig_node, tt_change,
tt_num_changes, ttvn);
- batadv_tt_save_orig_buffer(bat_priv, orig_node,
- (unsigned char *)tt_change, tt_num_changes);
+ batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
+ batadv_tt_len(tt_num_changes));
atomic_set(&orig_node->last_ttvn, ttvn);
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 08/16] batman-adv: Receive fragmented packets and merge
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Martin Hundebøll, Marek Lindner,
Antonio Quartulli
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Martin Hundebøll <martin@hundeboll.net>
Fragments arriving at their destination are buffered for later merge.
Merged packets are passed to the main receive function as had they never
been fragmented.
Fragments are forwarded without merging if the MTU of the outgoing
interface is smaller than the size of the merged packet.
Signed-off-by: Martin Hundebøll <martin@hundeboll.net>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/Makefile | 1 +
net/batman-adv/fragmentation.c | 370 ++++++++++++++++++++++++++++++++++++++++
net/batman-adv/fragmentation.h | 47 +++++
net/batman-adv/main.c | 4 +
net/batman-adv/main.h | 9 +
net/batman-adv/originator.c | 14 +-
net/batman-adv/packet.h | 27 +++
net/batman-adv/routing.c | 59 +++++++
net/batman-adv/routing.h | 2 +
net/batman-adv/soft-interface.c | 4 +
net/batman-adv/types.h | 38 +++++
11 files changed, 574 insertions(+), 1 deletion(-)
create mode 100644 net/batman-adv/fragmentation.c
create mode 100644 net/batman-adv/fragmentation.h
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index f9b465b..4f4aabb 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -24,6 +24,7 @@ batman-adv-y += bitarray.o
batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o
batman-adv-y += debugfs.o
batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o
+batman-adv-y += fragmentation.o
batman-adv-y += gateway_client.o
batman-adv-y += gateway_common.o
batman-adv-y += hard-interface.o
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
new file mode 100644
index 0000000..c829d3c
--- /dev/null
+++ b/net/batman-adv/fragmentation.c
@@ -0,0 +1,370 @@
+/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
+ *
+ * Martin Hundebøll <martin@hundeboll.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include "main.h"
+#include "fragmentation.h"
+#include "send.h"
+#include "originator.h"
+#include "routing.h"
+#include "hard-interface.h"
+#include "soft-interface.h"
+
+
+/**
+ * batadv_frag_clear_chain - delete entries in the fragment buffer chain
+ * @head: head of chain with entries.
+ *
+ * Free fragments in the passed hlist. Should be called with appropriate lock.
+ */
+static void batadv_frag_clear_chain(struct hlist_head *head)
+{
+ struct batadv_frag_list_entry *entry;
+ struct hlist_node *node;
+
+ hlist_for_each_entry_safe(entry, node, head, list) {
+ hlist_del(&entry->list);
+ kfree_skb(entry->skb);
+ kfree(entry);
+ }
+}
+
+/**
+ * batadv_frag_purge_orig - free fragments associated to an orig
+ * @orig_node: originator to free fragments from
+ * @check_cb: optional function to tell if an entry should be purged
+ */
+void batadv_frag_purge_orig(struct batadv_orig_node *orig_node,
+ bool (*check_cb)(struct batadv_frag_table_entry *))
+{
+ struct batadv_frag_table_entry *chain;
+ uint8_t i;
+
+ for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
+ chain = &orig_node->fragments[i];
+ spin_lock_bh(&orig_node->fragments[i].lock);
+
+ if (!check_cb || check_cb(chain)) {
+ batadv_frag_clear_chain(&orig_node->fragments[i].head);
+ orig_node->fragments[i].size = 0;
+ }
+
+ spin_unlock_bh(&orig_node->fragments[i].lock);
+ }
+}
+
+/**
+ * batadv_frag_size_limit - maximum possible size of packet to be fragmented
+ *
+ * Returns the maximum size of payload that can be fragmented.
+ */
+static int batadv_frag_size_limit(void)
+{
+ int limit = BATADV_FRAG_MAX_FRAG_SIZE;
+
+ limit -= sizeof(struct batadv_frag_packet);
+ limit *= BATADV_FRAG_MAX_FRAGMENTS;
+
+ return limit;
+}
+
+/**
+ * batadv_frag_init_chain - check and prepare fragment chain for new fragment
+ * @chain: chain in fragments table to init
+ * @seqno: sequence number of the received fragment
+ *
+ * Make chain ready for a fragment with sequence number "seqno". Delete existing
+ * entries if they have an "old" sequence number.
+ *
+ * Caller must hold chain->lock.
+ *
+ * Returns true if chain is empty and caller can just insert the new fragment
+ * without searching for the right position.
+ */
+static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain,
+ uint16_t seqno)
+{
+ if (chain->seqno == seqno)
+ return false;
+
+ if (!hlist_empty(&chain->head))
+ batadv_frag_clear_chain(&chain->head);
+
+ chain->size = 0;
+ chain->seqno = seqno;
+
+ return true;
+}
+
+/**
+ * batadv_frag_insert_packet - insert a fragment into a fragment chain
+ * @orig_node: originator that the fragment was received from
+ * @skb: skb to insert
+ * @chain_out: list head to attach complete chains of fragments to
+ *
+ * Insert a new fragment into the reverse ordered chain in the right table
+ * entry. The hash table entry is cleared if "old" fragments exist in it.
+ *
+ * Returns true if skb is buffered, false on error. If the chain has all the
+ * fragments needed to merge the packet, the chain is moved to the passed head
+ * to avoid locking the chain in the table.
+ */
+static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node,
+ struct sk_buff *skb,
+ struct hlist_head *chain_out)
+{
+ struct batadv_frag_table_entry *chain;
+ struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr;
+ struct batadv_frag_packet *frag_packet;
+ uint8_t bucket;
+ uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet);
+ bool ret = false;
+
+ /* Linearize packet to avoid linearizing 16 packets in a row when doing
+ * the later merge. Non-linear merge should be added to remove this
+ * linearization.
+ */
+ if (skb_linearize(skb) < 0)
+ goto err;
+
+ frag_packet = (struct batadv_frag_packet *)skb->data;
+ seqno = ntohs(frag_packet->seqno);
+ bucket = seqno % BATADV_FRAG_BUFFER_COUNT;
+
+ frag_entry_new = kmalloc(sizeof(*frag_entry_new), GFP_ATOMIC);
+ if (!frag_entry_new)
+ goto err;
+
+ frag_entry_new->skb = skb;
+ frag_entry_new->no = frag_packet->no;
+
+ /* Select entry in the "chain table" and delete any prior fragments
+ * with another sequence number. batadv_frag_init_chain() returns true,
+ * if the list is empty at return.
+ */
+ chain = &orig_node->fragments[bucket];
+ spin_lock_bh(&chain->lock);
+ if (batadv_frag_init_chain(chain, seqno)) {
+ hlist_add_head(&frag_entry_new->list, &chain->head);
+ chain->size = skb->len - hdr_size;
+ chain->timestamp = jiffies;
+ ret = true;
+ goto out;
+ }
+
+ /* Find the position for the new fragment. */
+ hlist_for_each_entry(frag_entry_curr, &chain->head, list) {
+ /* Drop packet if fragment already exists. */
+ if (frag_entry_curr->no == frag_entry_new->no)
+ goto err_unlock;
+
+ /* Order fragments from highest to lowest. */
+ if (frag_entry_curr->no < frag_entry_new->no) {
+ hlist_add_before(&frag_entry_new->list,
+ &frag_entry_curr->list);
+ chain->size += skb->len - hdr_size;
+ chain->timestamp = jiffies;
+ ret = true;
+ goto out;
+ }
+ }
+
+ /* Reached the end of the list, so insert after 'frag_entry_curr'. */
+ if (likely(frag_entry_curr)) {
+ hlist_add_after(&frag_entry_curr->list, &frag_entry_new->list);
+ chain->size += skb->len - hdr_size;
+ chain->timestamp = jiffies;
+ ret = true;
+ }
+
+out:
+ if (chain->size > batadv_frag_size_limit() ||
+ ntohs(frag_packet->total_size) > batadv_frag_size_limit()) {
+ /* Clear chain if total size of either the list or the packet
+ * exceeds the maximum size of one merged packet.
+ */
+ batadv_frag_clear_chain(&chain->head);
+ chain->size = 0;
+ } else if (ntohs(frag_packet->total_size) == chain->size) {
+ /* All fragments received. Hand over chain to caller. */
+ hlist_move_list(&chain->head, chain_out);
+ chain->size = 0;
+ }
+
+err_unlock:
+ spin_unlock_bh(&chain->lock);
+
+err:
+ if (!ret)
+ kfree(frag_entry_new);
+
+ return ret;
+}
+
+/**
+ * batadv_frag_merge_packets - merge a chain of fragments
+ * @chain: head of chain with fragments
+ * @skb: packet with total size of skb after merging
+ *
+ * Expand the first skb in the chain and copy the content of the remaining
+ * skb's into the expanded one. After doing so, clear the chain.
+ *
+ * Returns the merged skb or NULL on error.
+ */
+static struct sk_buff *
+batadv_frag_merge_packets(struct hlist_head *chain, struct sk_buff *skb)
+{
+ struct batadv_frag_packet *packet;
+ struct batadv_frag_list_entry *entry;
+ struct sk_buff *skb_out = NULL;
+ int size, hdr_size = sizeof(struct batadv_frag_packet);
+
+ /* Make sure incoming skb has non-bogus data. */
+ packet = (struct batadv_frag_packet *)skb->data;
+ size = ntohs(packet->total_size);
+ if (size > batadv_frag_size_limit())
+ goto free;
+
+ /* Remove first entry, as this is the destination for the rest of the
+ * fragments.
+ */
+ entry = hlist_entry(chain->first, struct batadv_frag_list_entry, list);
+ hlist_del(&entry->list);
+ skb_out = entry->skb;
+ kfree(entry);
+
+ /* Make room for the rest of the fragments. */
+ if (pskb_expand_head(skb_out, 0, size - skb->len, GFP_ATOMIC) < 0) {
+ kfree_skb(skb_out);
+ skb_out = NULL;
+ goto free;
+ }
+
+ /* Move the existing MAC header to just before the payload. (Override
+ * the fragment header.)
+ */
+ skb_pull_rcsum(skb_out, hdr_size);
+ memmove(skb_out->data - ETH_HLEN, skb_mac_header(skb_out), ETH_HLEN);
+ skb_set_mac_header(skb_out, -ETH_HLEN);
+ skb_reset_network_header(skb_out);
+ skb_reset_transport_header(skb_out);
+
+ /* Copy the payload of the each fragment into the last skb */
+ hlist_for_each_entry(entry, chain, list) {
+ size = entry->skb->len - hdr_size;
+ memcpy(skb_put(skb_out, size), entry->skb->data + hdr_size,
+ size);
+ }
+
+free:
+ /* Locking is not needed, because 'chain' is not part of any orig. */
+ batadv_frag_clear_chain(chain);
+ return skb_out;
+}
+
+/**
+ * batadv_frag_skb_buffer - buffer fragment for later merge
+ * @skb: skb to buffer
+ * @orig_node_src: originator that the skb is received from
+ *
+ * Add fragment to buffer and merge fragments if possible.
+ *
+ * There are three possible outcomes: 1) Packet is merged: Return true and
+ * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb
+ * to NULL; 3) Error: Return false and leave skb as is.
+ */
+bool batadv_frag_skb_buffer(struct sk_buff **skb,
+ struct batadv_orig_node *orig_node_src)
+{
+ struct sk_buff *skb_out = NULL;
+ struct hlist_head head = HLIST_HEAD_INIT;
+ bool ret = false;
+
+ /* Add packet to buffer and table entry if merge is possible. */
+ if (!batadv_frag_insert_packet(orig_node_src, *skb, &head))
+ goto out_err;
+
+ /* Leave if more fragments are needed to merge. */
+ if (hlist_empty(&head))
+ goto out;
+
+ skb_out = batadv_frag_merge_packets(&head, *skb);
+ if (!skb_out)
+ goto out_err;
+
+out:
+ *skb = skb_out;
+ ret = true;
+out_err:
+ return ret;
+}
+
+/**
+ * batadv_frag_skb_fwd - forward fragments that would exceed MTU when merged
+ * @skb: skb to forward
+ * @recv_if: interface that the skb is received on
+ * @orig_node_src: originator that the skb is received from
+ *
+ * Look up the next-hop of the fragments payload and check if the merged packet
+ * will exceed the MTU towards the next-hop. If so, the fragment is forwarded
+ * without merging it.
+ *
+ * Returns true if the fragment is consumed/forwarded, false otherwise.
+ */
+bool batadv_frag_skb_fwd(struct sk_buff *skb,
+ struct batadv_hard_iface *recv_if,
+ struct batadv_orig_node *orig_node_src)
+{
+ struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+ struct batadv_orig_node *orig_node_dst = NULL;
+ struct batadv_neigh_node *neigh_node = NULL;
+ struct batadv_frag_packet *packet;
+ uint16_t total_size;
+ bool ret = false;
+
+ packet = (struct batadv_frag_packet *)skb->data;
+ orig_node_dst = batadv_orig_hash_find(bat_priv, packet->dest);
+ if (!orig_node_dst)
+ goto out;
+
+ neigh_node = batadv_find_router(bat_priv, orig_node_dst, recv_if);
+ if (!neigh_node)
+ goto out;
+
+ /* Forward the fragment, if the merged packet would be too big to
+ * be assembled.
+ */
+ total_size = ntohs(packet->total_size);
+ if (total_size > neigh_node->if_incoming->net_dev->mtu) {
+ batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_FWD);
+ batadv_add_counter(bat_priv, BATADV_CNT_FRAG_FWD_BYTES,
+ skb->len + ETH_HLEN);
+
+ packet->header.ttl--;
+ batadv_send_skb_packet(skb, neigh_node->if_incoming,
+ neigh_node->addr);
+ ret = true;
+ }
+
+out:
+ if (orig_node_dst)
+ batadv_orig_node_free_ref(orig_node_dst);
+ if (neigh_node)
+ batadv_neigh_node_free_ref(neigh_node);
+ return ret;
+}
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
new file mode 100644
index 0000000..883a6f4
--- /dev/null
+++ b/net/batman-adv/fragmentation.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2013 B.A.T.M.A.N. contributors:
+ *
+ * Martin Hundebøll <martin@hundeboll.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#ifndef _NET_BATMAN_ADV_FRAGMENTATION_H_
+#define _NET_BATMAN_ADV_FRAGMENTATION_H_
+
+void batadv_frag_purge_orig(struct batadv_orig_node *orig,
+ bool (*check_cb)(struct batadv_frag_table_entry *));
+bool batadv_frag_skb_fwd(struct sk_buff *skb,
+ struct batadv_hard_iface *recv_if,
+ struct batadv_orig_node *orig_node_src);
+bool batadv_frag_skb_buffer(struct sk_buff **skb,
+ struct batadv_orig_node *orig_node);
+
+/**
+ * batadv_frag_check_entry - check if a list of fragments has timed out
+ * @frags_entry: table entry to check
+ *
+ * Returns true if the frags entry has timed out, false otherwise.
+ */
+static inline bool
+batadv_frag_check_entry(struct batadv_frag_table_entry *frags_entry)
+{
+ if (!hlist_empty(&frags_entry->head) &&
+ batadv_has_timed_out(frags_entry->timestamp, BATADV_FRAG_TIMEOUT))
+ return true;
+ else
+ return false;
+}
+
+#endif /* _NET_BATMAN_ADV_FRAGMENTATION_H_ */
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 8822fad..ca6f134 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -40,6 +40,7 @@
#include "hash.h"
#include "bat_algo.h"
#include "network-coding.h"
+#include "fragmentation.h"
/* List manipulations on hardif_list have to be rtnl_lock()'ed,
@@ -399,6 +400,7 @@ static void batadv_recv_handler_init(void)
BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
+ BUILD_BUG_ON(offsetof(struct batadv_frag_packet, dest) != 4);
BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
@@ -414,6 +416,8 @@ static void batadv_recv_handler_init(void)
batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
/* batman icmp packet */
batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
+ /* Fragmented packets */
+ batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_frag_packet;
}
int
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index e11c2ec..6a74a42 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -131,6 +131,15 @@ enum batadv_uev_type {
#define BATADV_GW_THRESHOLD 50
+/* Number of fragment chains for each orig_node */
+#define BATADV_FRAG_BUFFER_COUNT 8
+/* Maximum number of fragments for one packet */
+#define BATADV_FRAG_MAX_FRAGMENTS 16
+/* Maxumim size of each fragment */
+#define BATADV_FRAG_MAX_FRAG_SIZE 1400
+/* Time to keep fragments while waiting for rest of the fragments */
+#define BATADV_FRAG_TIMEOUT 10000
+
#define BATADV_DAT_CANDIDATE_NOT_FOUND 0
#define BATADV_DAT_CANDIDATE_ORIG 1
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 898b0ce..a591dc5 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -28,6 +28,7 @@
#include "soft-interface.h"
#include "bridge_loop_avoidance.h"
#include "network-coding.h"
+#include "fragmentation.h"
/* hash class keys */
static struct lock_class_key batadv_orig_hash_lock_class_key;
@@ -145,6 +146,8 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
/* Free nc_nodes */
batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
+ batadv_frag_purge_orig(orig_node, NULL);
+
batadv_tt_global_del_orig(orig_node->bat_priv, orig_node,
"originator timed out");
@@ -215,7 +218,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
const uint8_t *addr)
{
struct batadv_orig_node *orig_node;
- int size;
+ int size, i;
int hash_added;
unsigned long reset_time;
@@ -267,6 +270,12 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
size = bat_priv->num_ifaces * sizeof(uint8_t);
orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
+ for (i = 0; i < BATADV_FRAG_BUFFER_COUNT; i++) {
+ INIT_HLIST_HEAD(&orig_node->fragments[i].head);
+ spin_lock_init(&orig_node->fragments[i].lock);
+ orig_node->fragments[i].size = 0;
+ }
+
if (!orig_node->bcast_own_sum)
goto free_bcast_own;
@@ -388,6 +397,9 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
batadv_orig_node_free_ref(orig_node);
continue;
}
+
+ batadv_frag_purge_orig(orig_node,
+ batadv_frag_check_entry);
}
spin_unlock_bh(list_lock);
}
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 5e3b102..aa46c27 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -249,6 +249,33 @@ struct batadv_unicast_4addr_packet {
*/
};
+/**
+ * struct batadv_frag_packet - fragmented packet
+ * @header: common batman packet header with type, compatversion, and ttl
+ * @dest: final destination used when routing fragments
+ * @orig: originator of the fragment used when merging the packet
+ * @no: fragment number within this sequence
+ * @reserved: reserved byte for alignment
+ * @seqno: sequence identification
+ * @total_size: size of the merged packet
+ */
+struct batadv_frag_packet {
+ struct batadv_header header;
+#if defined(__BIG_ENDIAN_BITFIELD)
+ uint8_t no:4;
+ uint8_t reserved:4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+ uint8_t reserved:4;
+ uint8_t no:4;
+#else
+#error "unknown bitfield endianess"
+#endif
+ uint8_t dest[ETH_ALEN];
+ uint8_t orig[ETH_ALEN];
+ __be16 seqno;
+ __be16 total_size;
+};
+
struct batadv_bcast_packet {
struct batadv_header header;
uint8_t reserved;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index fd2cdbc..a080f63 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -28,6 +28,7 @@
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
#include "network-coding.h"
+#include "fragmentation.h"
static int batadv_route_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
@@ -1013,6 +1014,64 @@ int batadv_recv_unicast_tvlv(struct sk_buff *skb,
return ret;
}
+/**
+ * batadv_recv_frag_packet - process received fragment
+ * @skb: the received fragment
+ * @recv_if: interface that the skb is received on
+ *
+ * This function does one of the three following things: 1) Forward fragment, if
+ * the assembled packet will exceed our MTU; 2) Buffer fragment, if we till
+ * lack further fragments; 3) Merge fragments, if we have all needed parts.
+ *
+ * Return NET_RX_DROP if the skb is not consumed, NET_RX_SUCCESS otherwise.
+ */
+int batadv_recv_frag_packet(struct sk_buff *skb,
+ struct batadv_hard_iface *recv_if)
+{
+ struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+ struct batadv_orig_node *orig_node_src = NULL;
+ struct batadv_frag_packet *frag_packet;
+ int ret = NET_RX_DROP;
+
+ if (batadv_check_unicast_packet(bat_priv, skb,
+ sizeof(*frag_packet)) < 0)
+ goto out;
+
+ frag_packet = (struct batadv_frag_packet *)skb->data;
+ orig_node_src = batadv_orig_hash_find(bat_priv, frag_packet->orig);
+ if (!orig_node_src)
+ goto out;
+
+ /* Route the fragment if it is not for us and too big to be merged. */
+ if (!batadv_is_my_mac(bat_priv, frag_packet->dest) &&
+ batadv_frag_skb_fwd(skb, recv_if, orig_node_src)) {
+ ret = NET_RX_SUCCESS;
+ goto out;
+ }
+
+ batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX);
+ batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len);
+
+ /* Add fragment to buffer and merge if possible. */
+ if (!batadv_frag_skb_buffer(&skb, orig_node_src))
+ goto out;
+
+ /* Deliver merged packet to the appropriate handler, if it was
+ * merged
+ */
+ if (skb)
+ batadv_batman_skb_recv(skb, recv_if->net_dev,
+ &recv_if->batman_adv_ptype, NULL);
+
+ ret = NET_RX_SUCCESS;
+
+out:
+ if (orig_node_src)
+ batadv_orig_node_free_ref(orig_node_src);
+
+ return ret;
+}
+
int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if)
{
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index efab583..55d637a 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -30,6 +30,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
+int batadv_recv_frag_packet(struct sk_buff *skb,
+ struct batadv_hard_iface *iface);
int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_tt_query(struct sk_buff *skb,
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 504d0bb..dd189e6 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -758,6 +758,10 @@ static const struct {
{ "mgmt_tx_bytes" },
{ "mgmt_rx" },
{ "mgmt_rx_bytes" },
+ { "frag_rx" },
+ { "frag_rx_bytes" },
+ { "frag_fwd" },
+ { "frag_fwd_bytes" },
{ "tt_request_tx" },
{ "tt_request_rx" },
{ "tt_response_tx" },
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 795a079..5a2cc7a 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -86,6 +86,34 @@ struct batadv_hard_iface {
};
/**
+ * struct batadv_frag_table_entry - head in the fragment buffer table
+ * @head: head of list with fragments
+ * @lock: lock to protect the list of fragments
+ * @timestamp: time (jiffie) of last received fragment
+ * @seqno: sequence number of the fragments in the list
+ * @size: accumulated size of packets in list
+ */
+struct batadv_frag_table_entry {
+ struct hlist_head head;
+ spinlock_t lock; /* protects head */
+ unsigned long timestamp;
+ uint16_t seqno;
+ uint16_t size;
+};
+
+/**
+ * struct batadv_frag_list_entry - entry in a list of fragments
+ * @list: list node information
+ * @skb: fragment
+ * @no: fragment number in the set
+ */
+struct batadv_frag_list_entry {
+ struct hlist_node list;
+ struct sk_buff *skb;
+ uint8_t no;
+};
+
+/**
* struct batadv_orig_node - structure for orig_list maintaining nodes of mesh
* @orig: originator ethernet address
* @primary_addr: hosts primary interface address
@@ -128,6 +156,7 @@ struct batadv_hard_iface {
* @out_coding_list: list of nodes that can hear this orig
* @in_coding_list_lock: protects in_coding_list
* @out_coding_list_lock: protects out_coding_list
+ * @fragments: array with heads for fragment chains
*/
struct batadv_orig_node {
uint8_t orig[ETH_ALEN];
@@ -174,6 +203,7 @@ struct batadv_orig_node {
spinlock_t in_coding_list_lock; /* Protects in_coding_list */
spinlock_t out_coding_list_lock; /* Protects out_coding_list */
#endif
+ struct batadv_frag_table_entry fragments[BATADV_FRAG_BUFFER_COUNT];
};
/**
@@ -270,6 +300,10 @@ struct batadv_bcast_duplist_entry {
* @BATADV_CNT_MGMT_TX_BYTES: transmitted routing protocol traffic bytes counter
* @BATADV_CNT_MGMT_RX: received routing protocol traffic packet counter
* @BATADV_CNT_MGMT_RX_BYTES: received routing protocol traffic bytes counter
+ * @BATADV_CNT_FRAG_RX: received fragment traffic packet counter
+ * @BATADV_CNT_FRAG_RX_BYTES: received fragment traffic bytes counter
+ * @BATADV_CNT_FRAG_FWD: forwarded fragment traffic packet counter
+ * @BATADV_CNT_FRAG_FWD_BYTES: forwarded fragment traffic bytes counter
* @BATADV_CNT_TT_REQUEST_TX: transmitted tt req traffic packet counter
* @BATADV_CNT_TT_REQUEST_RX: received tt req traffic packet counter
* @BATADV_CNT_TT_RESPONSE_TX: transmitted tt resp traffic packet counter
@@ -307,6 +341,10 @@ enum batadv_counters {
BATADV_CNT_MGMT_TX_BYTES,
BATADV_CNT_MGMT_RX,
BATADV_CNT_MGMT_RX_BYTES,
+ BATADV_CNT_FRAG_RX,
+ BATADV_CNT_FRAG_RX_BYTES,
+ BATADV_CNT_FRAG_FWD,
+ BATADV_CNT_FRAG_FWD_BYTES,
BATADV_CNT_TT_REQUEST_TX,
BATADV_CNT_TT_REQUEST_RX,
BATADV_CNT_TT_RESPONSE_TX,
--
1.8.3.2
^ permalink raw reply related
* [PATCH 07/16] batman-adv: Remove old fragmentation code
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Martin Hundebøll, Marek Lindner,
Antonio Quartulli
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Martin Hundebøll <martin@hundeboll.net>
Remove the existing fragmentation code before adding the new version
and delete unicast.{h,c}.
batadv_unicast_send_skb() is moved to send.c and renamed to
batadv_send_skb_unicast().
fragmentation entry in sysfs (bat_priv->fragmentation) is kept for use in
the new fragmentation code.
BATADV_UNICAST_FRAG packet type is renamed to BATADV_FRAG for use in the
new fragmentation code.
Signed-off-by: Martin Hundebøll <martin@hundeboll.net>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/Makefile | 1 -
net/batman-adv/distributed-arp-table.c | 11 +-
net/batman-adv/hard-interface.c | 1 -
net/batman-adv/main.c | 4 -
net/batman-adv/originator.c | 9 -
net/batman-adv/packet.h | 16 --
net/batman-adv/routing.c | 86 +-----
net/batman-adv/routing.h | 2 -
net/batman-adv/send.c | 174 ++++++++++++
net/batman-adv/send.h | 40 +++
net/batman-adv/soft-interface.c | 4 +-
net/batman-adv/types.h | 19 --
net/batman-adv/unicast.c | 491 ---------------------------------
net/batman-adv/unicast.h | 92 ------
14 files changed, 221 insertions(+), 729 deletions(-)
delete mode 100644 net/batman-adv/unicast.c
delete mode 100644 net/batman-adv/unicast.h
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index 8ddbfe6..f9b465b 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -37,4 +37,3 @@ batman-adv-y += send.o
batman-adv-y += soft-interface.o
batman-adv-y += sysfs.o
batman-adv-y += translation-table.o
-batman-adv-y += unicast.o
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index f07ec32..99da412 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -29,7 +29,6 @@
#include "send.h"
#include "types.h"
#include "translation-table.h"
-#include "unicast.h"
static void batadv_dat_purge(struct work_struct *work);
@@ -592,9 +591,9 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
goto free_orig;
tmp_skb = pskb_copy(skb, GFP_ATOMIC);
- if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb,
- cand[i].orig_node,
- packet_subtype)) {
+ if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb,
+ cand[i].orig_node,
+ packet_subtype)) {
kfree_skb(tmp_skb);
goto free_neigh;
}
@@ -990,10 +989,10 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
* that a node not using the 4addr packet format doesn't support it.
*/
if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
- err = batadv_unicast_4addr_send_skb(bat_priv, skb_new,
+ err = batadv_send_skb_unicast_4addr(bat_priv, skb_new,
BATADV_P_DAT_CACHE_REPLY);
else
- err = batadv_unicast_send_skb(bat_priv, skb_new);
+ err = batadv_send_skb_unicast(bat_priv, skb_new);
if (!err) {
batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index eeb6671..0c8602e 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -444,7 +444,6 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
dev_add_pack(&hard_iface->batman_adv_ptype);
- atomic_set(&hard_iface->frag_seqno, 1);
batadv_info(hard_iface->soft_iface, "Adding interface: %s\n",
hard_iface->net_dev->name);
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 8b195e6..8822fad 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -36,7 +36,6 @@
#include "gateway_client.h"
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
-#include "unicast.h"
#include "gateway_common.h"
#include "hash.h"
#include "bat_algo.h"
@@ -399,7 +398,6 @@ static void batadv_recv_handler_init(void)
/* compile time checks for struct member offsets */
BUILD_BUG_ON(offsetof(struct batadv_unicast_4addr_packet, src) != 10);
BUILD_BUG_ON(offsetof(struct batadv_unicast_packet, dest) != 4);
- BUILD_BUG_ON(offsetof(struct batadv_unicast_frag_packet, dest) != 4);
BUILD_BUG_ON(offsetof(struct batadv_unicast_tvlv_packet, dst) != 4);
BUILD_BUG_ON(offsetof(struct batadv_icmp_packet, dst) != 4);
BUILD_BUG_ON(offsetof(struct batadv_icmp_packet_rr, dst) != 4);
@@ -412,8 +410,6 @@ static void batadv_recv_handler_init(void)
batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
/* unicast packet */
batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
- /* fragmented unicast packet */
- batadv_rx_handler[BATADV_UNICAST_FRAG] = batadv_recv_ucast_frag_packet;
/* unicast tvlv packet */
batadv_rx_handler[BATADV_UNICAST_TVLV] = batadv_recv_unicast_tvlv;
/* batman icmp packet */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 5d53d2f..898b0ce 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -25,7 +25,6 @@
#include "routing.h"
#include "gateway_client.h"
#include "hard-interface.h"
-#include "unicast.h"
#include "soft-interface.h"
#include "bridge_loop_avoidance.h"
#include "network-coding.h"
@@ -146,7 +145,6 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu)
/* Free nc_nodes */
batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL);
- batadv_frag_list_free(&orig_node->frag_list);
batadv_tt_global_del_orig(orig_node->bat_priv, orig_node,
"originator timed out");
@@ -269,9 +267,6 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
size = bat_priv->num_ifaces * sizeof(uint8_t);
orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
- INIT_LIST_HEAD(&orig_node->frag_list);
- orig_node->last_frag_packet = 0;
-
if (!orig_node->bcast_own_sum)
goto free_bcast_own;
@@ -393,10 +388,6 @@ static void _batadv_purge_orig(struct batadv_priv *bat_priv)
batadv_orig_node_free_ref(orig_node);
continue;
}
-
- if (batadv_has_timed_out(orig_node->last_frag_packet,
- BATADV_FRAG_TIMEOUT))
- batadv_frag_list_free(&orig_node->frag_list);
}
spin_unlock_bh(list_lock);
}
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 4361bae..5e3b102 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -91,12 +91,6 @@ enum batadv_icmp_packettype {
BATADV_PARAMETER_PROBLEM = 12,
};
-/* fragmentation defines */
-enum batadv_unicast_frag_flags {
- BATADV_UNI_FRAG_HEAD = BIT(0),
- BATADV_UNI_FRAG_LARGETAIL = BIT(1),
-};
-
/* tt data subtypes */
#define BATADV_TT_DATA_TYPE_MASK 0x0F
@@ -255,16 +249,6 @@ struct batadv_unicast_4addr_packet {
*/
};
-struct batadv_unicast_frag_packet {
- struct batadv_header header;
- uint8_t ttvn; /* destination translation table version number */
- uint8_t dest[ETH_ALEN];
- uint8_t flags;
- uint8_t align;
- uint8_t orig[ETH_ALEN];
- __be16 seqno;
-} __packed;
-
struct batadv_bcast_packet {
struct batadv_header header;
uint8_t reserved;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 0dc1c0e..fd2cdbc 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -25,7 +25,6 @@
#include "icmp_socket.h"
#include "translation-table.h"
#include "originator.h"
-#include "unicast.h"
#include "bridge_loop_avoidance.h"
#include "distributed-arp-table.h"
#include "network-coding.h"
@@ -653,11 +652,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
{
struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct batadv_orig_node *orig_node = NULL;
- struct batadv_neigh_node *neigh_node = NULL;
struct batadv_unicast_packet *unicast_packet;
struct ethhdr *ethhdr = eth_hdr(skb);
int res, hdr_len, ret = NET_RX_DROP;
- struct sk_buff *new_skb;
unicast_packet = (struct batadv_unicast_packet *)skb->data;
@@ -674,46 +671,12 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
if (!orig_node)
goto out;
- /* find_router() increases neigh_nodes refcount if found. */
- neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
-
- if (!neigh_node)
- goto out;
-
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, ETH_HLEN) < 0)
goto out;
- unicast_packet = (struct batadv_unicast_packet *)skb->data;
-
- if (unicast_packet->header.packet_type == BATADV_UNICAST &&
- atomic_read(&bat_priv->fragmentation) &&
- skb->len > neigh_node->if_incoming->net_dev->mtu) {
- ret = batadv_frag_send_skb(skb, bat_priv,
- neigh_node->if_incoming,
- neigh_node->addr);
- goto out;
- }
-
- if (unicast_packet->header.packet_type == BATADV_UNICAST_FRAG &&
- batadv_frag_can_reassemble(skb,
- neigh_node->if_incoming->net_dev->mtu)) {
- ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
-
- if (ret == NET_RX_DROP)
- goto out;
-
- /* packet was buffered for late merge */
- if (!new_skb) {
- ret = NET_RX_SUCCESS;
- goto out;
- }
-
- skb = new_skb;
- unicast_packet = (struct batadv_unicast_packet *)skb->data;
- }
-
/* decrement ttl */
+ unicast_packet = (struct batadv_unicast_packet *)skb->data;
unicast_packet->header.ttl--;
switch (unicast_packet->header.packet_type) {
@@ -748,8 +711,6 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
}
out:
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
if (orig_node)
batadv_orig_node_free_ref(orig_node);
return ret;
@@ -1003,51 +964,6 @@ rx_success:
return batadv_route_unicast_packet(skb, recv_if);
}
-int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
- struct batadv_hard_iface *recv_if)
-{
- struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
- struct batadv_unicast_frag_packet *unicast_packet;
- int hdr_size = sizeof(*unicast_packet);
- struct sk_buff *new_skb = NULL;
- int ret;
-
- if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
- return NET_RX_DROP;
-
- if (!batadv_check_unicast_ttvn(bat_priv, skb, hdr_size))
- return NET_RX_DROP;
-
- unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
-
- /* packet for me */
- if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
- ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
-
- if (ret == NET_RX_DROP)
- return NET_RX_DROP;
-
- /* packet was buffered for late merge */
- if (!new_skb)
- return NET_RX_SUCCESS;
-
- if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
- hdr_size))
- goto rx_success;
- if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
- hdr_size))
- goto rx_success;
-
- batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
- sizeof(struct batadv_unicast_packet), NULL);
-
-rx_success:
- return NET_RX_SUCCESS;
- }
-
- return batadv_route_unicast_packet(skb, recv_if);
-}
-
/**
* batadv_recv_unicast_tvlv - receive and process unicast tvlv packets
* @skb: unicast tvlv packet to process
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index ea15fa6..efab583 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -30,8 +30,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_unicast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
-int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
- struct batadv_hard_iface *recv_if);
int batadv_recv_bcast_packet(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
int batadv_recv_tt_query(struct sk_buff *skb,
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 81d69fb..b8356ec 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -25,6 +25,7 @@
#include "soft-interface.h"
#include "hard-interface.h"
#include "gateway_common.h"
+#include "gateway_client.h"
#include "originator.h"
#include "network-coding.h"
@@ -127,6 +128,179 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
return ret;
}
+/**
+ * batadv_send_skb_push_fill_unicast - extend the buffer and initialize the
+ * common fields for unicast packets
+ * @skb: the skb carrying the unicast header to initialize
+ * @hdr_size: amount of bytes to push at the beginning of the skb
+ * @orig_node: the destination node
+ *
+ * Returns false if the buffer extension was not possible or true otherwise.
+ */
+static bool
+batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
+ struct batadv_orig_node *orig_node)
+{
+ struct batadv_unicast_packet *unicast_packet;
+ uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+
+ if (batadv_skb_head_push(skb, hdr_size) < 0)
+ return false;
+
+ unicast_packet = (struct batadv_unicast_packet *)skb->data;
+ unicast_packet->header.version = BATADV_COMPAT_VERSION;
+ /* batman packet type: unicast */
+ unicast_packet->header.packet_type = BATADV_UNICAST;
+ /* set unicast ttl */
+ unicast_packet->header.ttl = BATADV_TTL;
+ /* copy the destination for faster routing */
+ memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+ /* set the destination tt version number */
+ unicast_packet->ttvn = ttvn;
+
+ return true;
+}
+
+/**
+ * batadv_send_skb_prepare_unicast - encapsulate an skb with a unicast header
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise.
+ */
+static bool batadv_send_skb_prepare_unicast(struct sk_buff *skb,
+ struct batadv_orig_node *orig_node)
+{
+ size_t uni_size = sizeof(struct batadv_unicast_packet);
+
+ return batadv_send_skb_push_fill_unicast(skb, uni_size, orig_node);
+}
+
+/**
+ * batadv_send_skb_prepare_unicast_4addr - encapsulate an skb with a
+ * unicast 4addr header
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ * @packet_subtype: the unicast 4addr packet subtype to use
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise.
+ */
+bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
+ struct sk_buff *skb,
+ struct batadv_orig_node *orig,
+ int packet_subtype)
+{
+ struct batadv_hard_iface *primary_if;
+ struct batadv_unicast_4addr_packet *uc_4addr_packet;
+ bool ret = false;
+
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out;
+
+ /* Pull the header space and fill the unicast_packet substructure.
+ * We can do that because the first member of the uc_4addr_packet
+ * is of type struct unicast_packet
+ */
+ if (!batadv_send_skb_push_fill_unicast(skb, sizeof(*uc_4addr_packet),
+ orig))
+ goto out;
+
+ uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+ uc_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+ memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN);
+ uc_4addr_packet->subtype = packet_subtype;
+ uc_4addr_packet->reserved = 0;
+
+ ret = true;
+out:
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ return ret;
+}
+
+/**
+ * batadv_send_generic_unicast_skb - send an skb as unicast
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @packet_type: the batman unicast packet type to use
+ * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast
+ * 4addr packets)
+ *
+ * Returns 1 in case of error or 0 otherwise.
+ */
+int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int packet_type,
+ int packet_subtype)
+{
+ struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+ struct batadv_unicast_packet *unicast_packet;
+ struct batadv_orig_node *orig_node;
+ struct batadv_neigh_node *neigh_node;
+ int ret = NET_RX_DROP;
+
+ /* get routing information */
+ if (is_multicast_ether_addr(ethhdr->h_dest)) {
+ orig_node = batadv_gw_get_selected_orig(bat_priv);
+ if (orig_node)
+ goto find_router;
+ }
+
+ /* check for tt host - increases orig_node refcount.
+ * returns NULL in case of AP isolation
+ */
+ orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
+ ethhdr->h_dest);
+
+find_router:
+ /* find_router():
+ * - if orig_node is NULL it returns NULL
+ * - increases neigh_nodes refcount if found.
+ */
+ neigh_node = batadv_find_router(bat_priv, orig_node, NULL);
+
+ if (!neigh_node)
+ goto out;
+
+ switch (packet_type) {
+ case BATADV_UNICAST:
+ batadv_send_skb_prepare_unicast(skb, orig_node);
+ break;
+ case BATADV_UNICAST_4ADDR:
+ batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, orig_node,
+ packet_subtype);
+ break;
+ default:
+ /* this function supports UNICAST and UNICAST_4ADDR only. It
+ * should never be invoked with any other packet type
+ */
+ goto out;
+ }
+
+ unicast_packet = (struct batadv_unicast_packet *)skb->data;
+
+ /* inform the destination node that we are still missing a correct route
+ * for this client. The destination will receive this packet and will
+ * try to reroute it because the ttvn contained in the header is less
+ * than the current one
+ */
+ if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest))
+ unicast_packet->ttvn = unicast_packet->ttvn - 1;
+
+ if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
+ ret = 0;
+
+out:
+ if (neigh_node)
+ batadv_neigh_node_free_ref(neigh_node);
+ if (orig_node)
+ batadv_orig_node_free_ref(orig_node);
+ if (ret == NET_RX_DROP)
+ kfree_skb(skb);
+ return ret;
+}
+
void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index e7b1788..ad63184 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -34,5 +34,45 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work);
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface);
+bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv,
+ struct sk_buff *skb,
+ struct batadv_orig_node *orig_node,
+ int packet_subtype);
+int batadv_send_skb_generic_unicast(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int packet_type,
+ int packet_subtype);
+
+
+/**
+ * batadv_send_unicast_skb - send the skb encapsulated in a unicast packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the payload to send
+ *
+ * Returns 1 in case of error or 0 otherwise.
+ */
+static inline int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
+ struct sk_buff *skb)
+{
+ return batadv_send_skb_generic_unicast(bat_priv, skb, BATADV_UNICAST,
+ 0);
+}
+
+/**
+ * batadv_send_4addr_unicast_skb - send the skb encapsulated in a unicast 4addr
+ * packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the payload to send
+ * @packet_subtype: the unicast 4addr packet subtype to use
+ *
+ * Returns 1 in case of error or 0 otherwise.
+ */
+static inline int batadv_send_skb_unicast_4addr(struct batadv_priv *bat_priv,
+ struct sk_buff *skb,
+ int packet_subtype)
+{
+ return batadv_send_skb_generic_unicast(bat_priv, skb,
+ BATADV_UNICAST_4ADDR,
+ packet_subtype);
+}
#endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 25e6004..504d0bb 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -34,8 +34,6 @@
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
-#include <linux/if_ether.h>
-#include "unicast.h"
#include "bridge_loop_avoidance.h"
#include "network-coding.h"
@@ -286,7 +284,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
- ret = batadv_unicast_send_skb(bat_priv, skb);
+ ret = batadv_send_skb_unicast(bat_priv, skb);
if (ret != 0)
goto dropped_freed;
}
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 8fbd89d..795a079 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -60,7 +60,6 @@ struct batadv_hard_iface_bat_iv {
* @if_num: identificator of the interface
* @if_status: status of the interface for batman-adv
* @net_dev: pointer to the net_device
- * @frag_seqno: last fragment sequence number sent by this interface
* @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
* @hardif_obj: kobject of the per interface sysfs "mesh" directory
* @refcount: number of contexts the object is used
@@ -76,7 +75,6 @@ struct batadv_hard_iface {
int16_t if_num;
char if_status;
struct net_device *net_dev;
- atomic_t frag_seqno;
uint8_t num_bcasts;
struct kobject *hardif_obj;
atomic_t refcount;
@@ -116,9 +114,6 @@ struct batadv_hard_iface {
* last_bcast_seqno)
* @last_bcast_seqno: last broadcast sequence number received by this host
* @neigh_list: list of potential next hop neighbor towards this orig node
- * @frag_list: fragmentation buffer list for fragment re-assembly
- * @last_frag_packet: time when last fragmented packet from this node was
- * received
* @neigh_list_lock: lock protecting neigh_list, router and bonding_list
* @hash_entry: hlist node for batadv_priv::orig_hash
* @bat_priv: pointer to soft_iface this orig node belongs to
@@ -159,8 +154,6 @@ struct batadv_orig_node {
DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
uint32_t last_bcast_seqno;
struct hlist_head neigh_list;
- struct list_head frag_list;
- unsigned long last_frag_packet;
/* neigh_list_lock protects: neigh_list, router & bonding_list */
spinlock_t neigh_list_lock;
struct hlist_node hash_entry;
@@ -874,18 +867,6 @@ struct batadv_forw_packet {
};
/**
- * struct batadv_frag_packet_list_entry - storage for fragment packet
- * @list: list node for orig_node::frag_list
- * @seqno: sequence number of the fragment
- * @skb: fragment's skb buffer
- */
-struct batadv_frag_packet_list_entry {
- struct list_head list;
- uint16_t seqno;
- struct sk_buff *skb;
-};
-
-/**
* struct batadv_algo_ops - mesh algorithm callbacks
* @list: list node for the batadv_algo_list
* @name: name of the algorithm
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
deleted file mode 100644
index 48b31d3..0000000
--- a/net/batman-adv/unicast.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
- *
- * Andreas Langer
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#include "main.h"
-#include "unicast.h"
-#include "send.h"
-#include "soft-interface.h"
-#include "gateway_client.h"
-#include "originator.h"
-#include "hash.h"
-#include "translation-table.h"
-#include "routing.h"
-#include "hard-interface.h"
-
-
-static struct sk_buff *
-batadv_frag_merge_packet(struct list_head *head,
- struct batadv_frag_packet_list_entry *tfp,
- struct sk_buff *skb)
-{
- struct batadv_unicast_frag_packet *up;
- struct sk_buff *tmp_skb;
- struct batadv_unicast_packet *unicast_packet;
- int hdr_len = sizeof(*unicast_packet);
- int uni_diff = sizeof(*up) - hdr_len;
- uint8_t *packet_pos;
-
- up = (struct batadv_unicast_frag_packet *)skb->data;
- /* set skb to the first part and tmp_skb to the second part */
- if (up->flags & BATADV_UNI_FRAG_HEAD) {
- tmp_skb = tfp->skb;
- } else {
- tmp_skb = skb;
- skb = tfp->skb;
- }
-
- if (skb_linearize(skb) < 0 || skb_linearize(tmp_skb) < 0)
- goto err;
-
- skb_pull(tmp_skb, sizeof(*up));
- if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0)
- goto err;
-
- /* move free entry to end */
- tfp->skb = NULL;
- tfp->seqno = 0;
- list_move_tail(&tfp->list, head);
-
- memcpy(skb_put(skb, tmp_skb->len), tmp_skb->data, tmp_skb->len);
- kfree_skb(tmp_skb);
-
- memmove(skb->data + uni_diff, skb->data, hdr_len);
- packet_pos = skb_pull(skb, uni_diff);
- unicast_packet = (struct batadv_unicast_packet *)packet_pos;
- unicast_packet->header.packet_type = BATADV_UNICAST;
-
- return skb;
-
-err:
- /* free buffered skb, skb will be freed later */
- kfree_skb(tfp->skb);
- return NULL;
-}
-
-static void batadv_frag_create_entry(struct list_head *head,
- struct sk_buff *skb)
-{
- struct batadv_frag_packet_list_entry *tfp;
- struct batadv_unicast_frag_packet *up;
-
- up = (struct batadv_unicast_frag_packet *)skb->data;
-
- /* free and oldest packets stand at the end */
- tfp = list_entry((head)->prev, typeof(*tfp), list);
- kfree_skb(tfp->skb);
-
- tfp->seqno = ntohs(up->seqno);
- tfp->skb = skb;
- list_move(&tfp->list, head);
- return;
-}
-
-static int batadv_frag_create_buffer(struct list_head *head)
-{
- int i;
- struct batadv_frag_packet_list_entry *tfp;
-
- for (i = 0; i < BATADV_FRAG_BUFFER_SIZE; i++) {
- tfp = kmalloc(sizeof(*tfp), GFP_ATOMIC);
- if (!tfp) {
- batadv_frag_list_free(head);
- return -ENOMEM;
- }
- tfp->skb = NULL;
- tfp->seqno = 0;
- INIT_LIST_HEAD(&tfp->list);
- list_add(&tfp->list, head);
- }
-
- return 0;
-}
-
-static struct batadv_frag_packet_list_entry *
-batadv_frag_search_packet(struct list_head *head,
- const struct batadv_unicast_frag_packet *up)
-{
- struct batadv_frag_packet_list_entry *tfp;
- struct batadv_unicast_frag_packet *tmp_up = NULL;
- bool is_head_tmp, is_head;
- uint16_t search_seqno;
-
- if (up->flags & BATADV_UNI_FRAG_HEAD)
- search_seqno = ntohs(up->seqno)+1;
- else
- search_seqno = ntohs(up->seqno)-1;
-
- is_head = up->flags & BATADV_UNI_FRAG_HEAD;
-
- list_for_each_entry(tfp, head, list) {
- if (!tfp->skb)
- continue;
-
- if (tfp->seqno == ntohs(up->seqno))
- goto mov_tail;
-
- tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data;
-
- if (tfp->seqno == search_seqno) {
- is_head_tmp = tmp_up->flags & BATADV_UNI_FRAG_HEAD;
- if (is_head_tmp != is_head)
- return tfp;
- else
- goto mov_tail;
- }
- }
- return NULL;
-
-mov_tail:
- list_move_tail(&tfp->list, head);
- return NULL;
-}
-
-void batadv_frag_list_free(struct list_head *head)
-{
- struct batadv_frag_packet_list_entry *pf, *tmp_pf;
-
- if (!list_empty(head)) {
- list_for_each_entry_safe(pf, tmp_pf, head, list) {
- kfree_skb(pf->skb);
- list_del(&pf->list);
- kfree(pf);
- }
- }
- return;
-}
-
-/* frag_reassemble_skb():
- * returns NET_RX_DROP if the operation failed - skb is left intact
- * returns NET_RX_SUCCESS if the fragment was buffered (skb_new will be NULL)
- * or the skb could be reassembled (skb_new will point to the new packet and
- * skb was freed)
- */
-int batadv_frag_reassemble_skb(struct sk_buff *skb,
- struct batadv_priv *bat_priv,
- struct sk_buff **new_skb)
-{
- struct batadv_orig_node *orig_node;
- struct batadv_frag_packet_list_entry *tmp_frag_entry;
- int ret = NET_RX_DROP;
- struct batadv_unicast_frag_packet *unicast_packet;
-
- unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
- *new_skb = NULL;
-
- orig_node = batadv_orig_hash_find(bat_priv, unicast_packet->orig);
- if (!orig_node)
- goto out;
-
- orig_node->last_frag_packet = jiffies;
-
- if (list_empty(&orig_node->frag_list) &&
- batadv_frag_create_buffer(&orig_node->frag_list)) {
- pr_debug("couldn't create frag buffer\n");
- goto out;
- }
-
- tmp_frag_entry = batadv_frag_search_packet(&orig_node->frag_list,
- unicast_packet);
-
- if (!tmp_frag_entry) {
- batadv_frag_create_entry(&orig_node->frag_list, skb);
- ret = NET_RX_SUCCESS;
- goto out;
- }
-
- *new_skb = batadv_frag_merge_packet(&orig_node->frag_list,
- tmp_frag_entry, skb);
- /* if not, merge failed */
- if (*new_skb)
- ret = NET_RX_SUCCESS;
-
-out:
- if (orig_node)
- batadv_orig_node_free_ref(orig_node);
- return ret;
-}
-
-int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
- struct batadv_hard_iface *hard_iface,
- const uint8_t dstaddr[])
-{
- struct batadv_unicast_packet tmp_uc, *unicast_packet;
- struct batadv_hard_iface *primary_if;
- struct sk_buff *frag_skb;
- struct batadv_unicast_frag_packet *frag1, *frag2;
- int uc_hdr_len = sizeof(*unicast_packet);
- int ucf_hdr_len = sizeof(*frag1);
- int data_len = skb->len - uc_hdr_len;
- int large_tail = 0, ret = NET_RX_DROP;
- uint16_t seqno;
-
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if)
- goto dropped;
-
- frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
- if (!frag_skb)
- goto dropped;
-
- skb->priority = TC_PRIO_CONTROL;
- skb_reserve(frag_skb, ucf_hdr_len);
-
- unicast_packet = (struct batadv_unicast_packet *)skb->data;
- memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
- skb_split(skb, frag_skb, data_len / 2 + uc_hdr_len);
-
- if (batadv_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
- batadv_skb_head_push(frag_skb, ucf_hdr_len) < 0)
- goto drop_frag;
-
- frag1 = (struct batadv_unicast_frag_packet *)skb->data;
- frag2 = (struct batadv_unicast_frag_packet *)frag_skb->data;
-
- memcpy(frag1, &tmp_uc, sizeof(tmp_uc));
-
- frag1->header.ttl--;
- frag1->header.version = BATADV_COMPAT_VERSION;
- frag1->header.packet_type = BATADV_UNICAST_FRAG;
-
- memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN);
- memcpy(frag2, frag1, sizeof(*frag2));
-
- if (data_len & 1)
- large_tail = BATADV_UNI_FRAG_LARGETAIL;
-
- frag1->flags = BATADV_UNI_FRAG_HEAD | large_tail;
- frag2->flags = large_tail;
-
- seqno = atomic_add_return(2, &hard_iface->frag_seqno);
- frag1->seqno = htons(seqno - 1);
- frag2->seqno = htons(seqno);
-
- batadv_send_skb_packet(skb, hard_iface, dstaddr);
- batadv_send_skb_packet(frag_skb, hard_iface, dstaddr);
- ret = NET_RX_SUCCESS;
- goto out;
-
-drop_frag:
- kfree_skb(frag_skb);
-dropped:
- kfree_skb(skb);
-out:
- if (primary_if)
- batadv_hardif_free_ref(primary_if);
- return ret;
-}
-
-/**
- * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the
- * common fields for unicast packets
- * @skb: packet
- * @hdr_size: amount of bytes to push at the beginning of the skb
- * @orig_node: the destination node
- *
- * Returns false if the buffer extension was not possible or true otherwise
- */
-static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
- struct batadv_orig_node *orig_node)
-{
- struct batadv_unicast_packet *unicast_packet;
- uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-
- if (batadv_skb_head_push(skb, hdr_size) < 0)
- return false;
-
- unicast_packet = (struct batadv_unicast_packet *)skb->data;
- unicast_packet->header.version = BATADV_COMPAT_VERSION;
- /* batman packet type: unicast */
- unicast_packet->header.packet_type = BATADV_UNICAST;
- /* set unicast ttl */
- unicast_packet->header.ttl = BATADV_TTL;
- /* copy the destination for faster routing */
- memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
- /* set the destination tt version number */
- unicast_packet->ttvn = ttvn;
-
- return true;
-}
-
-/**
- * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header
- * @skb: the skb containing the payload to encapsulate
- * @orig_node: the destination node
- *
- * Returns false if the payload could not be encapsulated or true otherwise.
- *
- * This call might reallocate skb data.
- */
-static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
- struct batadv_orig_node *orig_node)
-{
- size_t uni_size = sizeof(struct batadv_unicast_packet);
- return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node);
-}
-
-/**
- * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr
- * header
- * @bat_priv: the bat priv with all the soft interface information
- * @skb: the skb containing the payload to encapsulate
- * @orig_node: the destination node
- * @packet_subtype: the batman 4addr packet subtype to use
- *
- * Returns false if the payload could not be encapsulated or true otherwise.
- *
- * This call might reallocate skb data.
- */
-bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
- struct sk_buff *skb,
- struct batadv_orig_node *orig,
- int packet_subtype)
-{
- struct batadv_hard_iface *primary_if;
- struct batadv_unicast_4addr_packet *unicast_4addr_packet;
- bool ret = false;
-
- primary_if = batadv_primary_if_get_selected(bat_priv);
- if (!primary_if)
- goto out;
-
- /* pull the header space and fill the unicast_packet substructure.
- * We can do that because the first member of the unicast_4addr_packet
- * is of type struct unicast_packet
- */
- if (!batadv_unicast_push_and_fill_skb(skb,
- sizeof(*unicast_4addr_packet),
- orig))
- goto out;
-
- unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
- unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
- memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr,
- ETH_ALEN);
- unicast_4addr_packet->subtype = packet_subtype;
- unicast_4addr_packet->reserved = 0;
-
- ret = true;
-out:
- if (primary_if)
- batadv_hardif_free_ref(primary_if);
- return ret;
-}
-
-/**
- * batadv_unicast_generic_send_skb - send an skb as unicast
- * @bat_priv: the bat priv with all the soft interface information
- * @skb: payload to send
- * @packet_type: the batman unicast packet type to use
- * @packet_subtype: the batman packet subtype. It is ignored if packet_type is
- * not BATADV_UNICAT_4ADDR
- *
- * Returns 1 in case of error or 0 otherwise
- */
-int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
- struct sk_buff *skb, int packet_type,
- int packet_subtype)
-{
- struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
- struct batadv_unicast_packet *unicast_packet;
- struct batadv_orig_node *orig_node;
- struct batadv_neigh_node *neigh_node;
- int data_len = skb->len;
- int ret = NET_RX_DROP;
- unsigned int dev_mtu, header_len;
-
- /* get routing information */
- if (is_multicast_ether_addr(ethhdr->h_dest)) {
- orig_node = batadv_gw_get_selected_orig(bat_priv);
- if (orig_node)
- goto find_router;
- }
-
- /* check for tt host - increases orig_node refcount.
- * returns NULL in case of AP isolation
- */
- orig_node = batadv_transtable_search(bat_priv, ethhdr->h_source,
- ethhdr->h_dest);
-
-find_router:
- /* find_router():
- * - if orig_node is NULL it returns NULL
- * - increases neigh_nodes refcount if found.
- */
- neigh_node = batadv_find_router(bat_priv, orig_node, NULL);
-
- if (!neigh_node)
- goto out;
-
- switch (packet_type) {
- case BATADV_UNICAST:
- if (!batadv_unicast_prepare_skb(skb, orig_node))
- goto out;
-
- header_len = sizeof(struct batadv_unicast_packet);
- break;
- case BATADV_UNICAST_4ADDR:
- if (!batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
- packet_subtype))
- goto out;
-
- header_len = sizeof(struct batadv_unicast_4addr_packet);
- break;
- default:
- /* this function supports UNICAST and UNICAST_4ADDR only. It
- * should never be invoked with any other packet type
- */
- goto out;
- }
-
- ethhdr = (struct ethhdr *)(skb->data + header_len);
- unicast_packet = (struct batadv_unicast_packet *)skb->data;
-
- /* inform the destination node that we are still missing a correct route
- * for this client. The destination will receive this packet and will
- * try to reroute it because the ttvn contained in the header is less
- * than the current one
- */
- if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest))
- unicast_packet->ttvn = unicast_packet->ttvn - 1;
-
- dev_mtu = neigh_node->if_incoming->net_dev->mtu;
- /* fragmentation mechanism only works for UNICAST (now) */
- if (packet_type == BATADV_UNICAST &&
- atomic_read(&bat_priv->fragmentation) &&
- data_len + sizeof(*unicast_packet) > dev_mtu) {
- /* send frag skb decreases ttl */
- unicast_packet->header.ttl++;
- ret = batadv_frag_send_skb(skb, bat_priv,
- neigh_node->if_incoming,
- neigh_node->addr);
- goto out;
- }
-
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
- ret = 0;
-
-out:
- if (neigh_node)
- batadv_neigh_node_free_ref(neigh_node);
- if (orig_node)
- batadv_orig_node_free_ref(orig_node);
- if (ret == NET_RX_DROP)
- kfree_skb(skb);
- return ret;
-}
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
deleted file mode 100644
index 429cf8a..0000000
--- a/net/batman-adv/unicast.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2010-2013 B.A.T.M.A.N. contributors:
- *
- * Andreas Langer
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- */
-
-#ifndef _NET_BATMAN_ADV_UNICAST_H_
-#define _NET_BATMAN_ADV_UNICAST_H_
-
-#include "packet.h"
-
-#define BATADV_FRAG_TIMEOUT 10000 /* purge frag list entries after time in ms */
-#define BATADV_FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */
-
-int batadv_frag_reassemble_skb(struct sk_buff *skb,
- struct batadv_priv *bat_priv,
- struct sk_buff **new_skb);
-void batadv_frag_list_free(struct list_head *head);
-int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
- struct batadv_hard_iface *hard_iface,
- const uint8_t dstaddr[]);
-bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
- struct sk_buff *skb,
- struct batadv_orig_node *orig_node,
- int packet_subtype);
-int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
- struct sk_buff *skb, int packet_type,
- int packet_subtype);
-
-
-/**
- * batadv_unicast_send_skb - send the skb encapsulated in a unicast packet
- * @bat_priv: the bat priv with all the soft interface information
- * @skb: the payload to send
- */
-static inline int batadv_unicast_send_skb(struct batadv_priv *bat_priv,
- struct sk_buff *skb)
-{
- return batadv_unicast_generic_send_skb(bat_priv, skb, BATADV_UNICAST,
- 0);
-}
-
-/**
- * batadv_unicast_send_skb - send the skb encapsulated in a unicast4addr packet
- * @bat_priv: the bat priv with all the soft interface information
- * @skb: the payload to send
- * @packet_subtype: the batman 4addr packet subtype to use
- */
-static inline int batadv_unicast_4addr_send_skb(struct batadv_priv *bat_priv,
- struct sk_buff *skb,
- int packet_subtype)
-{
- return batadv_unicast_generic_send_skb(bat_priv, skb,
- BATADV_UNICAST_4ADDR,
- packet_subtype);
-}
-
-static inline int batadv_frag_can_reassemble(const struct sk_buff *skb, int mtu)
-{
- const struct batadv_unicast_frag_packet *unicast_packet;
- int uneven_correction = 0;
- unsigned int merged_size;
-
- unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
-
- if (unicast_packet->flags & BATADV_UNI_FRAG_LARGETAIL) {
- if (unicast_packet->flags & BATADV_UNI_FRAG_HEAD)
- uneven_correction = 1;
- else
- uneven_correction = -1;
- }
-
- merged_size = (skb->len - sizeof(*unicast_packet)) * 2;
- merged_size += sizeof(struct batadv_unicast_packet) + uneven_correction;
-
- return merged_size <= mtu;
-}
-
-#endif /* _NET_BATMAN_ADV_UNICAST_H_ */
--
1.8.3.2
^ permalink raw reply related
* [PATCH 09/16] batman-adv: Fragment and send skbs larger than mtu
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem
Cc: netdev, b.a.t.m.a.n, Martin Hundebøll, Marek Lindner,
Antonio Quartulli
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Martin Hundebøll <martin@hundeboll.net>
Non-broadcast packets larger than MTU are fragmented and sent with
an encapsulating header. Up to 16 fragments are supported, which are
sent in reverse order on the wire to allow minimal memory copying when
creating fragments.
Signed-off-by: Martin Hundebøll <martin@hundeboll.net>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
---
net/batman-adv/fragmentation.c | 121 ++++++++++++++++++++++++++++++++++++++++
net/batman-adv/fragmentation.h | 3 +
net/batman-adv/send.c | 21 +++++--
net/batman-adv/soft-interface.c | 7 +++
net/batman-adv/types.h | 6 ++
5 files changed, 154 insertions(+), 4 deletions(-)
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index c829d3c..271d321 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -368,3 +368,124 @@ out:
batadv_neigh_node_free_ref(neigh_node);
return ret;
}
+
+/**
+ * batadv_frag_create - create a fragment from skb
+ * @skb: skb to create fragment from
+ * @frag_head: header to use in new fragment
+ * @mtu: size of new fragment
+ *
+ * Split the passed skb into two fragments: A new one with size matching the
+ * passed mtu and the old one with the rest. The new skb contains data from the
+ * tail of the old skb.
+ *
+ * Returns the new fragment, NULL on error.
+ */
+static struct sk_buff *batadv_frag_create(struct sk_buff *skb,
+ struct batadv_frag_packet *frag_head,
+ unsigned int mtu)
+{
+ struct sk_buff *skb_fragment;
+ unsigned header_size = sizeof(*frag_head);
+ unsigned fragment_size = mtu - header_size;
+
+ skb_fragment = netdev_alloc_skb(NULL, mtu + ETH_HLEN);
+ if (!skb_fragment)
+ goto err;
+
+ skb->priority = TC_PRIO_CONTROL;
+
+ /* Eat the last mtu-bytes of the skb */
+ skb_reserve(skb_fragment, header_size + ETH_HLEN);
+ skb_split(skb, skb_fragment, skb->len - fragment_size);
+
+ /* Add the header */
+ skb_push(skb_fragment, header_size);
+ memcpy(skb_fragment->data, frag_head, header_size);
+
+err:
+ return skb_fragment;
+}
+
+/**
+ * batadv_frag_send_packet - create up to 16 fragments from the passed skb
+ * @skb: skb to create fragments from
+ * @orig_node: final destination of the created fragments
+ * @neigh_node: next-hop of the created fragments
+ *
+ * Returns true on success, false otherwise.
+ */
+bool batadv_frag_send_packet(struct sk_buff *skb,
+ struct batadv_orig_node *orig_node,
+ struct batadv_neigh_node *neigh_node)
+{
+ struct batadv_priv *bat_priv;
+ struct batadv_hard_iface *primary_if;
+ struct batadv_frag_packet frag_header;
+ struct sk_buff *skb_fragment;
+ unsigned mtu = neigh_node->if_incoming->net_dev->mtu;
+ unsigned header_size = sizeof(frag_header);
+ unsigned max_fragment_size, max_packet_size;
+
+ /* To avoid merge and refragmentation at next-hops we never send
+ * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
+ */
+ mtu = min_t(unsigned, mtu, BATADV_FRAG_MAX_FRAG_SIZE);
+ max_fragment_size = (mtu - header_size - ETH_HLEN);
+ max_packet_size = max_fragment_size * BATADV_FRAG_MAX_FRAGMENTS;
+
+ /* Don't even try to fragment, if we need more than 16 fragments */
+ if (skb->len > max_packet_size)
+ goto out_err;
+
+ bat_priv = orig_node->bat_priv;
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ goto out_err;
+
+ /* Create one header to be copied to all fragments */
+ frag_header.header.packet_type = BATADV_UNICAST_FRAG;
+ frag_header.header.version = BATADV_COMPAT_VERSION;
+ frag_header.header.ttl = BATADV_TTL;
+ frag_header.seqno = htons(atomic_inc_return(&bat_priv->frag_seqno));
+ frag_header.reserved = 0;
+ frag_header.no = 0;
+ frag_header.total_size = htons(skb->len);
+ memcpy(frag_header.orig, primary_if->net_dev->dev_addr, ETH_ALEN);
+ memcpy(frag_header.dest, orig_node->orig, ETH_ALEN);
+
+ /* Eat and send fragments from the tail of skb */
+ while (skb->len > max_fragment_size) {
+ skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
+ if (!skb_fragment)
+ goto out_err;
+
+ batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
+ batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
+ skb_fragment->len + ETH_HLEN);
+ batadv_send_skb_packet(skb_fragment, neigh_node->if_incoming,
+ neigh_node->addr);
+ frag_header.no++;
+
+ /* The initial check in this function should cover this case */
+ if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1)
+ goto out_err;
+ }
+
+ /* Make room for the fragment header. */
+ if (batadv_skb_head_push(skb, header_size) < 0 ||
+ pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0)
+ goto out_err;
+
+ memcpy(skb->data, &frag_header, header_size);
+
+ /* Send the last fragment */
+ batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
+ batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
+ skb->len + ETH_HLEN);
+ batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+
+ return true;
+out_err:
+ return false;
+}
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
index 883a6f4..ca029e2 100644
--- a/net/batman-adv/fragmentation.h
+++ b/net/batman-adv/fragmentation.h
@@ -27,6 +27,9 @@ bool batadv_frag_skb_fwd(struct sk_buff *skb,
struct batadv_orig_node *orig_node_src);
bool batadv_frag_skb_buffer(struct sk_buff **skb,
struct batadv_orig_node *orig_node);
+bool batadv_frag_send_packet(struct sk_buff *skb,
+ struct batadv_orig_node *orig_node,
+ struct batadv_neigh_node *neigh_node);
/**
* batadv_frag_check_entry - check if a list of fragments has timed out
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index b8356ec..1a1aa59 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -28,8 +28,7 @@
#include "gateway_client.h"
#include "originator.h"
#include "network-coding.h"
-
-#include <linux/if_ether.h>
+#include "fragmentation.h"
static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
@@ -109,7 +108,19 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
/* batadv_find_router() increases neigh_nodes refcount if found. */
neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
if (!neigh_node)
- return ret;
+ goto out;
+
+ /* Check if the skb is too large to send in one piece and fragment
+ * it if needed.
+ */
+ if (atomic_read(&bat_priv->fragmentation) &&
+ skb->len > neigh_node->if_incoming->net_dev->mtu) {
+ /* Fragment and send packet. */
+ if (batadv_frag_send_packet(skb, orig_node, neigh_node))
+ ret = NET_XMIT_SUCCESS;
+
+ goto out;
+ }
/* try to network code the packet, if it is received on an interface
* (i.e. being forwarded). If the packet originates from this node or if
@@ -123,7 +134,9 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
ret = NET_XMIT_SUCCESS;
}
- batadv_neigh_node_free_ref(neigh_node);
+out:
+ if (neigh_node)
+ batadv_neigh_node_free_ref(neigh_node);
return ret;
}
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index dd189e6..18b1fd9 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -442,6 +442,7 @@ static void batadv_softif_destroy_finish(struct work_struct *work)
static int batadv_softif_init_late(struct net_device *dev)
{
struct batadv_priv *bat_priv;
+ uint32_t random_seqno;
int ret;
size_t cnt_len = sizeof(uint64_t) * BATADV_CNT_NUM;
@@ -491,6 +492,10 @@ static int batadv_softif_init_late(struct net_device *dev)
bat_priv->tt.last_changeset = NULL;
bat_priv->tt.last_changeset_len = 0;
+ /* randomize initial seqno to avoid collision */
+ get_random_bytes(&random_seqno, sizeof(random_seqno));
+ atomic_set(&bat_priv->frag_seqno, random_seqno);
+
bat_priv->primary_if = NULL;
bat_priv->num_ifaces = 0;
@@ -758,6 +763,8 @@ static const struct {
{ "mgmt_tx_bytes" },
{ "mgmt_rx" },
{ "mgmt_rx_bytes" },
+ { "frag_tx" },
+ { "frag_tx_bytes" },
{ "frag_rx" },
{ "frag_rx_bytes" },
{ "frag_fwd" },
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 5a2cc7a..d517d5d 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -300,6 +300,8 @@ struct batadv_bcast_duplist_entry {
* @BATADV_CNT_MGMT_TX_BYTES: transmitted routing protocol traffic bytes counter
* @BATADV_CNT_MGMT_RX: received routing protocol traffic packet counter
* @BATADV_CNT_MGMT_RX_BYTES: received routing protocol traffic bytes counter
+ * @BATADV_CNT_FRAG_TX: transmitted fragment traffic packet counter
+ * @BATADV_CNT_FRAG_TX_BYTES: transmitted fragment traffic bytes counter
* @BATADV_CNT_FRAG_RX: received fragment traffic packet counter
* @BATADV_CNT_FRAG_RX_BYTES: received fragment traffic bytes counter
* @BATADV_CNT_FRAG_FWD: forwarded fragment traffic packet counter
@@ -341,6 +343,8 @@ enum batadv_counters {
BATADV_CNT_MGMT_TX_BYTES,
BATADV_CNT_MGMT_RX,
BATADV_CNT_MGMT_RX_BYTES,
+ BATADV_CNT_FRAG_TX,
+ BATADV_CNT_FRAG_TX_BYTES,
BATADV_CNT_FRAG_RX,
BATADV_CNT_FRAG_RX_BYTES,
BATADV_CNT_FRAG_FWD,
@@ -542,6 +546,7 @@ struct batadv_priv_nc {
* @aggregated_ogms: bool indicating whether OGM aggregation is enabled
* @bonding: bool indicating whether traffic bonding is enabled
* @fragmentation: bool indicating whether traffic fragmentation is enabled
+ * @frag_seqno: incremental counter to identify chains of egress fragments
* @ap_isolation: bool indicating whether ap isolation is enabled
* @bridge_loop_avoidance: bool indicating whether bridge loop avoidance is
* enabled
@@ -585,6 +590,7 @@ struct batadv_priv {
atomic_t aggregated_ogms;
atomic_t bonding;
atomic_t fragmentation;
+ atomic_t frag_seqno;
atomic_t ap_isolation;
#ifdef CONFIG_BATMAN_ADV_BLA
atomic_t bridge_loop_avoidance;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 06/16] batman-adv: use VLAN_ETH_HLEN instead of sizeof(struct vlan_eth_hdr)
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/bridge_loop_avoidance.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 264de88..70da18a 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1380,7 +1380,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb,
ethhdr = (struct ethhdr *)(((uint8_t *)skb->data) + hdr_size);
if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
- if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr)))
+ if (!pskb_may_pull(skb, hdr_size + VLAN_ETH_HLEN))
return 0;
vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size);
--
1.8.3.2
^ permalink raw reply related
* [PATCH 04/16] batman-adv: don't use call_rcu if not needed
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
batadv_tt_global_entry_free_ref uses call_rcu to schedule a
function which will only free the global entry itself.
For this reason call_rcu is useless and kfree_rcu can be
used to simplify the code.
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/translation-table.c | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index b3c4369..34fa6cc 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -117,25 +117,17 @@ batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
kfree_rcu(tt_local_entry, common.rcu);
}
-static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
-{
- struct batadv_tt_common_entry *tt_common_entry;
- struct batadv_tt_global_entry *tt_global_entry;
-
- tt_common_entry = container_of(rcu, struct batadv_tt_common_entry, rcu);
- tt_global_entry = container_of(tt_common_entry,
- struct batadv_tt_global_entry, common);
-
- kfree(tt_global_entry);
-}
-
+/**
+ * batadv_tt_global_entry_free_ref - decrement the refcounter for a
+ * tt_global_entry and possibly free it
+ * @tt_global_entry: the object to free
+ */
static void
batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
{
if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
batadv_tt_global_del_orig_list(tt_global_entry);
- call_rcu(&tt_global_entry->common.rcu,
- batadv_tt_global_entry_free_rcu);
+ kfree_rcu(tt_global_entry, common.rcu);
}
}
--
1.8.3.2
^ permalink raw reply related
* [PATCH 05/16] batman-adv: h_vlan_encapsulated_proto access refactoring
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
In case of a VLAN tagged frame the ethhdr pointer is
moved forward by 4 bytes so that the offset of h_proto
in struct ethhdr matches the real
h_vlan_encapsulated_proto address in the skb. While this
trickery is correct it makes the code harder to understand
and may lead to bugs in case of re-use of ethhdr for other
purposes.
This patch introduces a proto variable to make things
cleaner and easier to understand.
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/gateway_client.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 1bce63a..ac97ca7 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -655,24 +655,29 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
struct iphdr *iphdr;
struct ipv6hdr *ipv6hdr;
struct udphdr *udphdr;
+ struct vlan_ethhdr *vhdr;
+ __be16 proto;
/* check for ethernet header */
if (!pskb_may_pull(skb, *header_len + ETH_HLEN))
return false;
ethhdr = (struct ethhdr *)skb->data;
+ proto = ethhdr->h_proto;
*header_len += ETH_HLEN;
/* check for initial vlan header */
- if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) {
+ if (proto == htons(ETH_P_8021Q)) {
if (!pskb_may_pull(skb, *header_len + VLAN_HLEN))
return false;
- ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN);
+
+ vhdr = (struct vlan_ethhdr *)skb->data;
+ proto = vhdr->h_vlan_encapsulated_proto;
*header_len += VLAN_HLEN;
}
/* check for ip header */
- switch (ntohs(ethhdr->h_proto)) {
- case ETH_P_IP:
+ switch (proto) {
+ case htons(ETH_P_IP):
if (!pskb_may_pull(skb, *header_len + sizeof(*iphdr)))
return false;
iphdr = (struct iphdr *)(skb->data + *header_len);
@@ -683,7 +688,7 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
return false;
break;
- case ETH_P_IPV6:
+ case htons(ETH_P_IPV6):
if (!pskb_may_pull(skb, *header_len + sizeof(*ipv6hdr)))
return false;
ipv6hdr = (struct ipv6hdr *)(skb->data + *header_len);
@@ -710,11 +715,11 @@ bool batadv_gw_is_dhcp_target(struct sk_buff *skb, unsigned int *header_len)
*header_len += sizeof(*udphdr);
/* check for bootp port */
- if ((ntohs(ethhdr->h_proto) == ETH_P_IP) &&
+ if ((proto == htons(ETH_P_IP)) &&
(ntohs(udphdr->dest) != 67))
return false;
- if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) &&
+ if ((proto == htons(ETH_P_IPV6)) &&
(ntohs(udphdr->dest) != 547))
return false;
--
1.8.3.2
^ permalink raw reply related
* [PATCH 03/16] batman-adv: remove batadv_tt_global_add_orig declaration
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
batadv_tt_global_add_orig is neither used nor implemented
anymore, therefore it is possible to remove its declaration
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/translation-table.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index fb710c5..015d8b9 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -27,9 +27,6 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
const uint8_t *addr, const char *message,
bool roaming);
int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
-void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
- struct batadv_orig_node *orig_node,
- const unsigned char *tt_buff, int tt_buff_len);
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
--
1.8.3.2
^ permalink raw reply related
* [PATCH 02/16] batman-adv: make tt_global_add static and return bool
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem; +Cc: netdev, b.a.t.m.a.n, Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio@meshcoding.com>
From: Antonio Quartulli <ordex@autistici.org>
batadv_tt_global_add is not used anymore outside of the TT
code thanks to the TVLV implementation. It can therefore be
declared as static
Last user has been removed by 3de4e64df0f1326db7cc0ef25f5af8522850252d
("batman-adv: tvlv - convert roaming adv packet to use tvlv unicast packets")
Moreover make it return bool since its result can be either 0 or 1.
Reported-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
---
net/batman-adv/translation-table.c | 14 ++++++++------
net/batman-adv/translation-table.h | 4 ----
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index c741694..b3c4369 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -805,15 +805,17 @@ out:
* If a TT local entry exists for this non-mesh client remove it.
*
* The caller must hold orig_node refcount.
+ *
+ * Return true if the new entry has been added, false otherwise
*/
-int batadv_tt_global_add(struct batadv_priv *bat_priv,
- struct batadv_orig_node *orig_node,
- const unsigned char *tt_addr, uint16_t flags,
- uint8_t ttvn)
+static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
+ struct batadv_orig_node *orig_node,
+ const unsigned char *tt_addr, uint16_t flags,
+ uint8_t ttvn)
{
struct batadv_tt_global_entry *tt_global_entry;
struct batadv_tt_local_entry *tt_local_entry;
- int ret = 0;
+ bool ret = false;
int hash_added;
struct batadv_tt_common_entry *common;
uint16_t local_flags;
@@ -914,7 +916,7 @@ add_orig_entry:
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new global tt entry: %pM (via %pM)\n",
common->addr, orig_node->orig);
- ret = 1;
+ ret = true;
out_remove:
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index b4b6dea..fb710c5 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -30,10 +30,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *tt_buff, int tt_buff_len);
-int batadv_tt_global_add(struct batadv_priv *bat_priv,
- struct batadv_orig_node *orig_node,
- const unsigned char *addr, uint16_t flags,
- uint8_t ttvn);
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
--
1.8.3.2
^ permalink raw reply related
* [PATCH 01/16] batman-adv: only add recordroute information to icmp request/reply
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r, Simon Wunderlich,
Antonio Quartulli, Marek Lindner
In-Reply-To: <1381663381-626-1-git-send-email-antonio-x4xJYDvStAgysxA8WJXlww@public.gmane.org>
From: Simon Wunderlich <simon.wunderlich-Y4E02TeZ33kaBlGTGt4zH4SGEyLTKazZ@public.gmane.org>
Adding host information for record route is only required for ICMP
requests and replys, and should not be added to just any (future?)
packet type.
Signed-off-by: Simon Wunderlich <siwu-MaAgPAbsBIVS8oHt8HbXEIQuADTiUCJX@public.gmane.org>
Signed-off-by: Marek Lindner <lindner_marek-LWAfsSFWpa4@public.gmane.org>
Signed-off-by: Antonio Quartulli <antonio-x4xJYDvStAgysxA8WJXlww@public.gmane.org>
---
net/batman-adv/routing.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 457dfef..0dc1c0e 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -379,7 +379,9 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
/* add record route information if not full */
- if ((hdr_size == sizeof(struct batadv_icmp_packet_rr)) &&
+ if ((icmp_packet->msg_type == BATADV_ECHO_REPLY ||
+ icmp_packet->msg_type == BATADV_ECHO_REQUEST) &&
+ (hdr_size == sizeof(struct batadv_icmp_packet_rr)) &&
(icmp_packet->rr_cur < BATADV_RR_LEN)) {
memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
ethhdr->h_dest, ETH_ALEN);
--
1.8.3.2
^ permalink raw reply related
* pull request: batman-adv 2013-10-13
From: Antonio Quartulli @ 2013-10-13 11:22 UTC (permalink / raw)
To: davem-fT/PcQaiUtIeIZ0/mPfg9Q
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
b.a.t.m.a.n-ZwoEplunGu2X36UT3dwllkB+6BGkLq7r
Hello David,
this is our second pull request intended for net-next/linux-3.13.
The most important piece in this patchset is the new packet fragmentation code
implemented by Martin Hundebøll during his Google Summer of Code 2012[1]. This
code is entirely substituting the current fragmentation mechanism.
Other than this you have:
- the creation of a common BAT ICMP header which makes the ICMP subsystem more
flexible and extensible
- the addition of a dummy rx mode handler for the soft-interface which allows
users to set static multicast listeners
- some minor improvements and code cleanups
Please pull or let me know of any problem.
Thank you very much,
Antonio
[1] http://www.open-mesh.org/projects/batman-adv/wiki/Fragmentation
The following changes since commit ccdbb6e96beca362db876d820ac1e560ff6d9579:
tcp: tcp_transmit_skb() optimizations (2013-10-11 17:48:18 -0400)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batman-adv-for-davem
for you to fetch changes up to a4deee1ad42d93746562fe7de2149729017e3fd1:
batman-adv: Add dummy soft-interface rx mode handler (2013-10-12 17:17:12 +0200)
----------------------------------------------------------------
Included changes:
- ensure RecordRoute information is added to BAT_ICMP echo_request/reply only
- use VLAN_ETH_HLEN when possible
- use htons when possible
- substitute old fragmentation code with a new improved implementation by
Martin Hundebøll
- create common header for BAT_ICMP packets to improve extendibility
- consider the network coding overhead when computing the overall room needed by
batman headers
- add dummy soft-interface rx mode handler
- minor code refactoring and cleanups
----------------------------------------------------------------
Antonio Quartulli (9):
batman-adv: make tt_global_add static and return bool
batman-adv: remove batadv_tt_global_add_orig declaration
batman-adv: don't use call_rcu if not needed
batman-adv: h_vlan_encapsulated_proto access refactoring
batman-adv: use VLAN_ETH_HLEN instead of sizeof(struct vlan_eth_hdr)
batman-adv: use htons when possible
batman-adv: create common header for ICMP packets
batman-adv: implement batadv_tt_entries
batman-adv: make batadv_tt_save_orig_buffer() generic
Linus Lüssing (1):
batman-adv: Add dummy soft-interface rx mode handler
Marek Lindner (1):
batman-adv: consider network coding overhead when calculating required mtu
Martin Hundebøll (3):
batman-adv: Remove old fragmentation code
batman-adv: Receive fragmented packets and merge
batman-adv: Fragment and send skbs larger than mtu
Simon Wunderlich (2):
batman-adv: only add recordroute information to icmp request/reply
batman-adv: remove useless find_router look up
net/batman-adv/Makefile | 2 +-
net/batman-adv/bridge_loop_avoidance.c | 14 +-
net/batman-adv/distributed-arp-table.c | 11 +-
net/batman-adv/fragmentation.c | 491 +++++++++++++++++++++++++++++++++
net/batman-adv/fragmentation.h | 50 ++++
net/batman-adv/gateway_client.c | 23 +-
net/batman-adv/hard-interface.c | 22 +-
net/batman-adv/icmp_socket.c | 22 +-
net/batman-adv/main.c | 37 ++-
net/batman-adv/main.h | 10 +
net/batman-adv/originator.c | 19 +-
net/batman-adv/packet.h | 79 ++++--
net/batman-adv/routing.c | 185 ++++++-------
net/batman-adv/routing.h | 4 +-
net/batman-adv/send.c | 186 ++++++++++++-
net/batman-adv/send.h | 40 +++
net/batman-adv/soft-interface.c | 34 ++-
net/batman-adv/translation-table.c | 63 +++--
net/batman-adv/translation-table.h | 7 -
net/batman-adv/types.h | 70 +++--
net/batman-adv/unicast.c | 491 ---------------------------------
net/batman-adv/unicast.h | 92 ------
22 files changed, 1105 insertions(+), 847 deletions(-)
create mode 100644 net/batman-adv/fragmentation.c
create mode 100644 net/batman-adv/fragmentation.h
delete mode 100644 net/batman-adv/unicast.c
delete mode 100644 net/batman-adv/unicast.h
^ permalink raw reply
* Re: [PATCH v3 tip/core/rcu 0/14] Sparse-related updates for 3.13
From: Paul E. McKenney @ 2013-10-13 11:17 UTC (permalink / raw)
To: Josh Triplett, peterz, fweisbec, dhowells, edumazet, gaofeng,
mingo, bridge, jmorris, dipankar, darren, rostedt, niv,
mathieu.desnoyers, kuznet, tglx, johannes, laijs, yoshfuji,
netdev, linux-decnet-user, linux-kernel, kaber, stephen, sbw,
tgraf, akpm, fengguang.wu, davem
In-Reply-To: <20131012174354.GE20321@order.stressinduktion.org>
On Sat, Oct 12, 2013 at 07:43:54PM +0200, Hannes Frederic Sowa wrote:
> On Sat, Oct 12, 2013 at 07:39:30PM +0200, Hannes Frederic Sowa wrote:
> > On Sat, Oct 12, 2013 at 10:13:45AM -0700, Paul E. McKenney wrote:
> > > On Fri, Oct 11, 2013 at 11:53:27PM -0700, Josh Triplett wrote:
> > > > On Fri, Oct 11, 2013 at 04:16:59PM -0700, Paul E. McKenney wrote:
> > > > > Changes from v2:
> > > > >
> > > > > o Switch from rcu_assign_pointer() to ACCESS_ONCE() given that
> > > > > the pointers are all --rcu and already visible to readers,
> > > > > as suggested by Eric Dumazet and Josh Triplett.
> > > >
> > > > Hang on a moment. Do *none* of these cases need write memory barriers?
> > >
> > > Sigh. Some afternoons it doesn't pay to touch the keyboard.
> > >
> > > Thank you for catching this. I will fix, but at this point, I am thinking
> > > in terms of 3.14 rather than 3.13 for this series.
> >
> > Some of them looked safe. You could also replace --rcu with __rcu in the
> > comments while at it.
>
> Most of them deal with management, maybe a rtnl_assign_pointer with lockdep
> check for rtnl lock could help to not clean up the wrong bits.
>
> I don't know if rtnl_assign_pointer is that a could name as it does not really
> explain why the barrier is not needed there. :/
Beyond a certain point, I need to let people who know more about Linux's
networking implementation handle this sort of thing.
Thanx, Paul
^ permalink raw reply
* Re: [Bridge] [PATCH v3 tip/core/rcu 0/14] Sparse-related updates for 3.13
From: Paul E. McKenney @ 2013-10-13 11:15 UTC (permalink / raw)
To: Josh Triplett, peterz, fweisbec, dhowells, edumazet, gaofeng,
mingo, bridge, jmorris, dipankar, darren, rostedt, niv,
mathieu.desnoyers, kuznet, tglx, johannes, laijs, yoshfuji,
netdev, linux-decnet-user, linux-kernel, kaber, stephen, sbw,
tgraf, akpm, fengguang.wu, davem
In-Reply-To: <20131012173930.GD20321@order.stressinduktion.org>
On Sat, Oct 12, 2013 at 07:39:30PM +0200, Hannes Frederic Sowa wrote:
> On Sat, Oct 12, 2013 at 10:13:45AM -0700, Paul E. McKenney wrote:
> > On Fri, Oct 11, 2013 at 11:53:27PM -0700, Josh Triplett wrote:
> > > On Fri, Oct 11, 2013 at 04:16:59PM -0700, Paul E. McKenney wrote:
> > > > Changes from v2:
> > > >
> > > > o Switch from rcu_assign_pointer() to ACCESS_ONCE() given that
> > > > the pointers are all --rcu and already visible to readers,
> > > > as suggested by Eric Dumazet and Josh Triplett.
> > >
> > > Hang on a moment. Do *none* of these cases need write memory barriers?
> >
> > Sigh. Some afternoons it doesn't pay to touch the keyboard.
> >
> > Thank you for catching this. I will fix, but at this point, I am thinking
> > in terms of 3.14 rather than 3.13 for this series.
>
> Some of them looked safe. You could also replace --rcu with __rcu in the
> comments while at it.
Sigh! Will do, thank you!
Thanx, Paul
^ permalink raw reply
* Re: [PATCH v2 tip/core/rcu 07/13] ipv6/ip6_tunnel: Apply rcu_access_pointer() to avoid sparse false positive
From: Paul E. McKenney @ 2013-10-13 11:14 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Hannes Frederic Sowa, Eric Dumazet, Josh Triplett, linux-kernel,
mingo, laijs, dipankar, akpm, niv, tglx, peterz, rostedt,
dhowells, edumazet, darren, fweisbec, sbw, David S. Miller,
Alexey Kuznetsov, James Morris, Hideaki YOSHIFUJI,
Patrick McHardy, netdev
In-Reply-To: <1882655271.38519.1381606938076.JavaMail.zimbra@efficios.com>
On Sat, Oct 12, 2013 at 07:42:18PM +0000, Mathieu Desnoyers wrote:
> ----- Original Message -----
> > On Sat, Oct 12, 2013 at 06:43:45PM +0200, Hannes Frederic Sowa wrote:
> > > Regarding the volatile access, I hope that the C11 memory model
> > > and enhancements to the compiler will some day provide a better
> > > way to express the semantics of what is tried to express here
> > > (__atomic_store_n/__atomic_load_n with the accompanied memory model,
> > > which could be even weaker to what a volatile access would enfore
> > > now and could guarantee atomic stores/loads).
> >
> > I just played around a bit more. Perhaps we could try to warn of silly
> > usages of ACCESS_ONCE():
> >
> > --- a/include/linux/compiler.h
> > +++ b/include/linux/compiler.h
> > @@ -349,7 +349,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f,
> > int val, int expect);
> > * use is to mediate communication between process-level code and irq/NMI
> > * handlers, all running on the same CPU.
> > */
> > -#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
> > +#define ACCESS_ONCE(x) (*({ \
> > + compiletime_assert(sizeof(typeof(x)) <= sizeof(typeof(&x)), \
> > + "ACCESS_ONCE likely not atomic"); \
>
> AFAIU, ACCESS_ONCE() is not meant to ensure atomicity of load/store,
> but rather merely ensures that the compiler will not merge nor refetch
> accesses. I don't think the assert check you propose is appropriate with
> respect to the ACCESS_ONCE() semantic.
I am with Mathieu on this one, at least unless there is some set of actual
bugs already in the kernel that these length checks would find.
/me wonders about structs of size 3, 5, 6, and 7...
Thanx, Paul
> Thanks,
>
> Mathieu
>
> > + (volatile typeof(x) *)&(x); \
> > +}))
> >
> > /* Ignore/forbid kprobes attach on very low level functions marked by this
> > attribute: */
> > #ifdef CONFIG_KPROBES
> >
> >
>
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com
>
^ permalink raw reply
* Re: IPv6 path MTU discovery broken
From: Steinar H. Gunderson @ 2013-10-13 10:40 UTC (permalink / raw)
To: Hannes Frederic Sowa; +Cc: netdev, edumazet, fan.du
In-Reply-To: <20131007030910.GG9295@order.stressinduktion.org>
[resending with proper quoting and cc]
On Mon, Oct 07, 2013 at 05:09:10AM +0200, Hannes Frederic Sowa wrote:
> Could you try to check (with e.g. nstat) if any of the following counters
> change if the icmp messages hit the host?
>
> TcpExtOutOfWindowIcmps
> Icmp6InErrors
> TcpExtTCPMinTTLDrop
> TcpExtListenDrops
Hi,
I am now seeing the same problem against a 3.9.0 machine (that I've never had
problems with before). I looked through the four nstat counters, and none of
them are increasing. Here's /proc/net/ipv6_route from the server while it's
going on; the client is 2001:67c:a4:1:71f9:c84b:8b2a:c65b (second line) and
the server is 2001:67c:29f4::2007.
20010500002e00000000000000000001 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
2001067c00a4000171f9c84b8b2ac65b 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000003 000005fb 01000023 eth0.10
2001067c2804100100000000c21f2797 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
2001067c29f400000000000000000021 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000002 00000723 01000001 eth0.10
2001067c29f400000000000000000022 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 0000003c 01000001 eth0.10
2001067c29f400000000000000000029 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 0000000c 025f8b9d 01000001 eth0.10
2001067c29f400000000000000000031 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 000000c5 01000001 eth0.10
2001067c29f400000000000000000052 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000040 01000001 eth0.10
2001067c29f400000000000000000056 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 00001a37 01000001 eth0.10
2001067c29f400000000000000000065 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000041 01000001 eth0.10
2001067c29f400000000000000000070 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 000073fb 01000001 eth0.10
2001067c29f400000000000000000072 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000002 01000001 eth0.10
2001067c29f400000000000000000086 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 0000244b 01000001 eth0.10
2001067c29f400000000000000002010 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000020 01000001 eth0.10
2001067c29f400000000000000002012 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 000001d6 01000001 eth0.10
2001067c29f400000000000000003001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 0000005f 01000001 eth0.10
2001067c29f400000000000000005001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000001 01000001 eth0.10
2001067c29f400000000000000005015 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000016 01000001 eth0.10
2001067c29f400000000000000005201 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 0000509f 01000001 eth0.10
2001067c29f400000000000000005205 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 00039f0b 01000001 eth0.10
2001067c29f400000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000001 00000001 eth0.10
200107000300146281ec7e498c3e8d5e 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
200141d0006000000000000000000012 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
20014600000400110000000000000005 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000003 01000003 eth0.10
20014600000410120000000000000005 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
20014600000410120000000000000006 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
20014600000410120000000000000007 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
20014801000d00000000000000530001 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
2406da00ff0000000000000036d3b443 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
2406da00ff0000000000000036e313b8 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
26003c03000000000000000000000003 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
2607f8b040020c010000000000000154 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
2a001450400b0c010000000000000154 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
2a00145040130c00000000000000005f 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000002 01000003 eth0.10
2a0103b0000100fa000000000000000f 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
2a020fe0000100020001000000010110 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000003 01000003 eth0.10
2a028070000002010082021200620039 80 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000000 00000000 00000001 01000003 eth0.10
fe800000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0
fe800000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0.10
fe800000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0.4
00000000000000000000000000000000 00 00000000000000000000000000000000 00 2001067c29f400000000000000000001 00000400 00000000 00000000 00000003 eth0.10
00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 0a896d3b 00200200 lo
00000000000000000000000000000001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000002 3348a5ad 80200001 lo
2001067c29f400000000000000000028 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 01afbbc1 80200001 lo
2001067c29f400000000000000000030 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000020 29f1bc63 80200001 lo
2001067c29f400000000000000000049 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 03174149 80200001 lo
2001067c29f400000000000000002001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 000b20f8 80200001 lo
2001067c29f400000000000000002002 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 0003c38f 80200001 lo
2001067c29f400000000000000002003 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 000bf060 80200001 lo
2001067c29f400000000000000002004 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 0000e383 80200001 lo
2001067c29f400000000000000002005 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 00058cae 80200001 lo
2001067c29f400000000000000002006 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 000082f7 80200001 lo
2001067c29f400000000000000002007 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000003 001a353e 80200001 lo
fe80000000000000022590fffec352c8 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 00000000 80200001 lo
fe80000000000000022590fffec352c8 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 0020538d 80200001 lo
fe80000000000000022590fffec352c8 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000001 00000000 80200001 lo
ff020000000000000000000000000001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000003 01000001 eth0.10
ff020000000000000000000000000002 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000001 01000001 eth0.10
ff02000000000000000000000000000d 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000003 01000001 eth0.10
ff020000000000000000000000010003 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 0000000e 01000001 eth0.10
ff0200000000000000000001ff000030 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000002 01000001 eth0.10
ff0200000000000000000001ff000031 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000002 01000001 eth0.10
ff0200000000000000000001ff003005 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000003 01000001 eth0.10
ff0200000000000000000001ff006001 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000001 01000001 eth0.10
ff0200000000000000000001ff2c2de5 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000001 01000001 eth0.10
ff0200000000000000000001ff4793da 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000001 01000001 eth0.10
ff0200000000000000000001ff555743 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000001 01000001 eth0.10
ff0200000000000000000001ff5945c2 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000007 01000001 eth0.10
ff0200000000000000000001ffdae370 80 00000000000000000000000000000000 00 00000000000000000000000000000000 00000000 00000000 00000002 01000001 eth0.10
ff000000000000000000000000000000 08 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0
ff000000000000000000000000000000 08 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0.10
ff000000000000000000000000000000 08 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0.4
00000000000000000000000000000000 00 00000000000000000000000000000000 00 00000000000000000000000000000000 ffffffff 00000001 0a896d3b 00200200 lo
/* Steinar */
--
Homepage: http://www.sesse.net/
^ permalink raw reply
* DaVinci Emac Driver Fails to wake up on suspending to RAM
From: Prabhakar Lad @ 2013-10-13 7:28 UTC (permalink / raw)
To: dlos, Mugunthan V N, netdev
Hi,
While testing the suspend to RAM on OMAP-L138, I see a issue while waking up
the request irq fails with following log.
Linux version is Linux version 3.12.0-rc2
root@da850-omapl138-evm:~# rtcwake -d /dev/rtc0 -s 20 -m mem
wakeup from "mem" at Sat Jan 1 00:01:47 2000
PM: Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.001 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
Suspending console(s) (use no_console_suspend to debug)
PM: suspend of devices complete after 8.693 msecs
PM: suspend devices took 0.010 seconds
PM: late suspend of devices complete after 3.096 msecs
PM: noirq suspend of devices complete after 2.989 msecs
PM: noirq resume of devices complete after 2.396 msecs
PM: early resume of devices complete after 2.851 msecs
genirq: Flags mismatch irq 33. 00000000 (eth0) vs. 00000000 (eth0)
net eth0: DaVinci EMAC: devm_request_irq() failed
PM: resume of devices complete after 15.857 msecs
PM: resume devices took 0.020 seconds
Restarting tasks ... done.
nfs: server 169.254.80.251 not responding, still trying
nfs: server 169.254.80.251 not responding, still trying
--
Regards,
--Prabhakar Lad
^ permalink raw reply
* Re: [Patch 1/1]: libertas/sdio: fix releasing memory twice.
From: Dr. H. Nikolaus Schaller @ 2013-10-13 7:09 UTC (permalink / raw)
To: Dan Williams
Cc: John W. Linville, Bing Zhao, Harro Haan, libertas-dev,
linux-wireless, netdev, LKML, Belisko Marek, NeilBrown Brown
In-Reply-To: <1381607911.21655.7.camel@dcbw.foobar.com>
Hi Dan,
Am 12.10.2013 um 21:58 schrieb Dan Williams:
> On Sat, 2013-10-12 at 18:02 +0200, Dr. H. Nikolaus Schaller wrote:
>> While upgrading the GTA04 kernel to 3.12-rc4 we came across
>> an issue with libertas/sdio referencing stale memory on ifconfig up
>> when trying to load the firmware (for a second time).
>>
>> I am not at all sure if the patch is how it should be done and the right
>> location, but it appears to work for us with resetting priv->helper_fw to NULL
>> before asynchronously loading the firmware again.
>
> How about we go even simpler? helper_fw is *only* used inside
> firmware.c anyway, and that's probably where its lifetime should be
> handled. Same for the main firmware. I have no idea why the bus code
> is responsible for releasing the firmware anyway, when it originates
> from firmware.c and control returns back there after the firmware loaded
> callback is done. Does the following patch fix your problem too?
Yes, it works!
I think your approach is much better from software architecture point
of view than our hack.
Thank you,
Nikolaus
>
> Dan
>
> ---
> diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c
> index c0f9e7e..51b92b5 100644
> --- a/drivers/net/wireless/libertas/firmware.c
> +++ b/drivers/net/wireless/libertas/firmware.c
> @@ -49,14 +49,19 @@ static void main_firmware_cb(const struct firmware *firmware, void *context)
> /* Failed to find firmware: try next table entry */
> load_next_firmware_from_table(priv);
> return;
> }
>
> /* Firmware found! */
> lbs_fw_loaded(priv, 0, priv->helper_fw, firmware);
> + if (priv->helper_fw) {
> + release_firmware (priv->helper_fw);
> + priv->helper_fw = NULL;
> + }
> + release_firmware (firmware);
> }
>
> static void helper_firmware_cb(const struct firmware *firmware, void *context)
> {
> struct lbs_private *priv = context;
>
> if (!firmware) {
> diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
> index c94dd68..ef8c98e 100644
> --- a/drivers/net/wireless/libertas/if_cs.c
> +++ b/drivers/net/wireless/libertas/if_cs.c
> @@ -750,22 +750,22 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
> }
>
> /* Load the firmware */
> ret = if_cs_prog_helper(card, helper);
> if (ret == 0 && (card->model != MODEL_8305))
> ret = if_cs_prog_real(card, mainfw);
> if (ret)
> - goto out;
> + return;
>
> /* Now actually get the IRQ */
> ret = request_irq(card->p_dev->irq, if_cs_interrupt,
> IRQF_SHARED, DRV_NAME, card);
> if (ret) {
> pr_err("error in request_irq\n");
> - goto out;
> + return;
> }
>
> /*
> * Clear any interrupt cause that happened while sending
> * firmware/initializing card
> */
> if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
> @@ -773,18 +773,14 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
>
> /* And finally bring the card up */
> priv->fw_ready = 1;
> if (lbs_start_card(priv) != 0) {
> pr_err("could not activate card\n");
> free_irq(card->p_dev->irq, card);
> }
> -
> -out:
> - release_firmware(helper);
> - release_firmware(mainfw);
> }
>
>
> /********************************************************************/
> /* Callback functions for libertas.ko */
> /********************************************************************/
>
> diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
> index 4557833..991238a 100644
> --- a/drivers/net/wireless/libertas/if_sdio.c
> +++ b/drivers/net/wireless/libertas/if_sdio.c
> @@ -704,28 +704,24 @@ static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret,
> if (ret) {
> pr_err("failed to find firmware (%d)\n", ret);
> return;
> }
>
> ret = if_sdio_prog_helper(card, helper);
> if (ret)
> - goto out;
> + return;
>
> lbs_deb_sdio("Helper firmware loaded\n");
>
> ret = if_sdio_prog_real(card, mainfw);
> if (ret)
> - goto out;
> + return;
>
> lbs_deb_sdio("Firmware loaded\n");
> if_sdio_finish_power_on(card);
> -
> -out:
> - release_firmware(helper);
> - release_firmware(mainfw);
> }
>
> static int if_sdio_prog_firmware(struct if_sdio_card *card)
> {
> int ret;
> u16 scratch;
>
> diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
> index 4bb6574..87ff0ca 100644
> --- a/drivers/net/wireless/libertas/if_spi.c
> +++ b/drivers/net/wireless/libertas/if_spi.c
> @@ -1090,19 +1090,15 @@ static int if_spi_init_card(struct if_spi_card *card)
> }
>
> err = spu_set_interrupt_mode(card, 0, 1);
> if (err)
> goto out;
>
> out:
> - release_firmware(helper);
> - release_firmware(mainfw);
> -
> lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
> -
> return err;
> }
>
> static void if_spi_resume_worker(struct work_struct *work)
> {
> struct if_spi_card *card;
>
> diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
> index 2798077..dff08a2 100644
> --- a/drivers/net/wireless/libertas/if_usb.c
> +++ b/drivers/net/wireless/libertas/if_usb.c
> @@ -840,15 +840,15 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
> pr_err("failed to find firmware (%d)\n", ret);
> goto done;
> }
>
> cardp->fw = fw;
> if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
> ret = -EINVAL;
> - goto release_fw;
> + goto done;
> }
>
> /* Cancel any pending usb business */
> usb_kill_urb(cardp->rx_urb);
> usb_kill_urb(cardp->tx_urb);
>
> cardp->fwlastblksent = 0;
> @@ -857,15 +857,15 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
> cardp->fwfinalblk = 0;
> cardp->bootcmdresp = 0;
>
> restart:
> if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
> lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
> ret = -EIO;
> - goto release_fw;
> + goto done;
> }
>
> cardp->bootcmdresp = 0;
> do {
> int j = 0;
> i++;
> if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB);
> @@ -879,22 +879,22 @@ restart:
> if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) {
> /* Return to normal operation */
> ret = -EOPNOTSUPP;
> usb_kill_urb(cardp->rx_urb);
> usb_kill_urb(cardp->tx_urb);
> if (if_usb_submit_rx_urb(cardp) < 0)
> ret = -EIO;
> - goto release_fw;
> + goto done;
> } else if (cardp->bootcmdresp <= 0) {
> if (--reset_count >= 0) {
> if_usb_reset_device(cardp);
> goto restart;
> }
> ret = -EIO;
> - goto release_fw;
> + goto done;
> }
>
> i = 0;
>
> cardp->totalbytes = 0;
> cardp->fwlastblksent = 0;
> cardp->CRC_OK = 1;
> @@ -917,37 +917,34 @@ restart:
> if (--reset_count >= 0) {
> if_usb_reset_device(cardp);
> goto restart;
> }
>
> pr_info("FW download failure, time = %d ms\n", i * 100);
> ret = -EIO;
> - goto release_fw;
> + goto done;
> }
>
> cardp->priv->fw_ready = 1;
> if_usb_submit_rx_urb(cardp);
>
> if (lbs_start_card(priv))
> - goto release_fw;
> + goto done;
>
> if_usb_setup_firmware(priv);
>
> /*
> * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware.
> */
> priv->wol_criteria = EHS_REMOVE_WAKEUP;
> if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
> priv->ehs_remove_supported = false;
>
> - release_fw:
> - release_firmware(cardp->fw);
> - cardp->fw = NULL;
> -
> done:
> + cardp->fw = NULL;
> lbs_deb_leave(LBS_DEB_USB);
> }
>
>
> #ifdef CONFIG_PM
> static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
> {
>
>
^ permalink raw reply
* [PATCH] irda: update comment mentioning IRQF_DISABLED
From: Michael Opdenacker @ 2013-10-13 6:26 UTC (permalink / raw)
To: samuel, davem; +Cc: netdev, linux-kernel, Michael Opdenacker
This patch removes a comment mentioning IRQF_DISABLED,
which is deprecated.
Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com>
---
include/net/irda/irda_device.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
index 94c852d..1141747 100644
--- a/include/net/irda/irda_device.h
+++ b/include/net/irda/irda_device.h
@@ -162,7 +162,7 @@ typedef struct {
int irq, irq2; /* Interrupts used */
int dma, dma2; /* DMA channel(s) used */
int fifo_size; /* FIFO size */
- int irqflags; /* interrupt flags (ie, IRQF_SHARED|IRQF_DISABLED) */
+ int irqflags; /* interrupt flags (ie, IRQF_SHARED) */
int direction; /* Link direction, used by some FIR drivers */
int enabled; /* Powered on? */
int suspended; /* Suspended by APM */
--
1.8.1.2
^ permalink raw reply related
* RE: [PATCH] bnx2x: record rx queue for LRO packets
From: Dmitry Kravkov @ 2013-10-13 6:23 UTC (permalink / raw)
To: Eric Dumazet, David Miller; +Cc: netdev, Eilon Greenstein, Willem de Bruijn
In-Reply-To: <1381612114.3392.14.camel@edumazet-glaptop.roam.corp.google.com>
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-
> owner@vger.kernel.org] On Behalf Of Eric Dumazet
> Sent: Sunday, October 13, 2013 12:09 AM
> To: David Miller
> Cc: netdev; Eilon Greenstein; Willem de Bruijn
> Subject: [PATCH] bnx2x: record rx queue for LRO packets
>
> From: Eric Dumazet <edumazet@google.com>
>
> RPS support is kind of broken on bnx2x, because only non LRO packets get
> proper rx queue information. This triggers reorders, as it seems bnx2x like to
> generate a non LRO packet for segment including TCP PUSH flag : (this might
> be pure coincidence, but all the reorders I've seen involve segments with a
> PUSH)
>
> 11:13:34.335847 IP A > B: . 415808:447136(31328) ack 1 win 457
> <nop,nop,timestamp 3789336 3985797>
> 11:13:34.335992 IP A > B: . 447136:448560(1424) ack 1 win 457
> <nop,nop,timestamp 3789336 3985797>
> 11:13:34.336391 IP A > B: . 448560:479888(31328) ack 1 win 457
> <nop,nop,timestamp 3789337 3985797>
> 11:13:34.336425 IP A > B: P 511216:512640(1424) ack 1 win 457
> <nop,nop,timestamp 3789337 3985798>
> 11:13:34.336423 IP A > B: . 479888:511216(31328) ack 1 win 457
> <nop,nop,timestamp 3789337 3985798>
> 11:13:34.336924 IP A > B: . 512640:543968(31328) ack 1 win 457
> <nop,nop,timestamp 3789337 3985798>
> 11:13:34.336963 IP A > B: . 543968:575296(31328) ack 1 win 457
> <nop,nop,timestamp 3789337 3985798>
>
> We must call skb_record_rx_queue() to properly give to RPS (and more
> generally for TX queue selection on forward path) the receive queue
> information.
>
> Similar fix is needed for skb_mark_napi_id(), but will be handled in a
> separate patch to ease stable backports.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Willem de Bruijn <willemb@google.com>
> Cc: Eilon Greenstein <eilong@broadcom.com>
> ---
> drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 +
> 1 file changed, 1 insertion(+)
Thanks!
Acked-by: Dmitry Kravkov <dmitry@broadcom.com>
^ permalink raw reply
* [PATCH] isdn: remove deprecated IRQF_DISABLED
From: Michael Opdenacker @ 2013-10-13 5:24 UTC (permalink / raw)
To: mac, isdn; +Cc: netdev, linux-kernel, davem, Michael Opdenacker
This patch proposes to remove the use of the IRQF_DISABLED flag
It's a NOOP since 2.6.35 and it will be removed one day.
Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com>
---
drivers/isdn/hardware/eicon/divasmain.c | 2 +-
drivers/isdn/sc/init.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c
index 52377b4..a2e0ed6 100644
--- a/drivers/isdn/hardware/eicon/divasmain.c
+++ b/drivers/isdn/hardware/eicon/divasmain.c
@@ -481,7 +481,7 @@ void __inline__ outpp(void __iomem *addr, word p)
int diva_os_register_irq(void *context, byte irq, const char *name)
{
int result = request_irq(irq, diva_os_irq_wrapper,
- IRQF_DISABLED | IRQF_SHARED, name, context);
+ IRQF_SHARED, name, context);
return (result);
}
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index ca997bd..92acc81 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -336,7 +336,7 @@ static int __init sc_init(void)
*/
sc_adapter[cinst]->interrupt = irq[b];
if (request_irq(sc_adapter[cinst]->interrupt, interrupt_handler,
- IRQF_DISABLED, interface->id,
+ 0, interface->id,
(void *)(unsigned long) cinst))
{
kfree(sc_adapter[cinst]->channel);
--
1.8.1.2
^ permalink raw reply related
* RE: [PATCH 1/1] net: fix cipso packet validation when !NETLABEL
From: Seif Mazareeb @ 2013-10-13 5:21 UTC (permalink / raw)
To: Paul Moore
Cc: davem@davemloft.net, netdev@vger.kernel.org,
thomas.petazzoni@free-electrons.com, Dmitri Epshtein
In-Reply-To: <2291823.ee0I8c00DA@olly>
When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could loop
forever in the main loop if opt[opt_iter +1] == 0, this will causing a kernel
crash in an SMP system, since the CPU executing this function will
stall /not respond to IPIs.
This problem can be reproduced by running the IP Stack Integrity Checker
(http://isic.sourceforge.net) using the following command on a Linux machine
connected to DUT:
"icmpsic -s rand -d <DUT IP address> -r 123456"
wait (1-2 min)
Signed-off-by: Seif Mazareeb <seif@marvell.com>
---
include/net/cipso_ipv4.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index a7a683e..a8c2ef6 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
unsigned char err_offset = 0;
u8 opt_len = opt[1];
u8 opt_iter;
+ u8 tag_len;
if (opt_len < 8) {
err_offset = 1;
@@ -302,11 +303,12 @@ static inline int cipso_v4_validate(const struct sk_buff *skb,
}
for (opt_iter = 6; opt_iter < opt_len;) {
- if (opt[opt_iter + 1] > (opt_len - opt_iter)) {
+ tag_len = opt[opt_iter + 1];
+ if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) {
err_offset = opt_iter + 1;
goto out;
}
- opt_iter += opt[opt_iter + 1];
+ opt_iter += tag_len;
}
out:
--
1.8.1.2
-----Original Message-----
From: Paul Moore [mailto:paul@paul-moore.com]
Sent: Saturday, October 12, 2013 4:57 AM
To: Seif Mazareeb
Cc: davem@davemloft.net; netdev@vger.kernel.org; thomas.petazzoni@free-electrons.com; Dmitri Epshtein
Subject: Re: [PATCH 1/1] net: fix cipso packet validation when !NETLABEL
On Friday, October 11, 2013 2:04:10 PM Seif Mazareeb wrote:
> When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function
> could loop forever in the main loop if opt[opt_iter +1] == 0, this
> will causing a kernel crash in an SMP system, since the CPU executing
> this function will stall /not respond to IPIs.
>
> This problem can be reproduced by running the IP Stack Integrity
> Checker
> (http://isic.sourceforge.net) using the following command on a Linux
> machine connected to DUT:
>
> "icmpsic -s rand -d <DUT IP address> -r 123456"
> wait (1-2 min)
>
> Signed-off-by: Seif Mazareeb <seif@marvell.com>
> ---
> include/net/cipso_ipv4.h | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index
> a7a683e..286b7da 100644
> --- a/include/net/cipso_ipv4.h
> +++ b/include/net/cipso_ipv4.h
> @@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct
> sk_buff *skb, unsigned char err_offset = 0;
> u8 opt_len = opt[1];
> u8 opt_iter;
> + u8 tag_len;
>
> if (opt_len < 8) {
> err_offset = 1;
> @@ -302,7 +303,8 @@ static inline int cipso_v4_validate(const struct
> sk_buff *skb, }
>
> for (opt_iter = 6; opt_iter < opt_len;) {
> - if (opt[opt_iter + 1] > (opt_len - opt_iter)) {
> + tag_len = opt[opt_iter + 1];
> + if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len -
> opt_iter))) { err_offset = opt_iter + 1;
> goto out;
> }
You should also use 'tag_len' inside the for-loop, and after the if-block, where we increment 'opt_iter'. See my original reply for an example.
--
paul moore
www.paul-moore.com
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox