Hi,
here is the third version of the throughput meter support. It is just a
rebased version of the patchset with two little bugfixes. Both problems were
detected and reported by Antonio:
* batctl didn't check if the test_time is > 0 before doing a division
* batman-adv wasn't returning an error to batctl when dst was not reachable
I am currently unsure how we should proceed regarding the ICMP packet type
used to communicate to the userspace ([PATCH 2/3]). Andrew+Matthias already
prepared a netlink patchset which looks quite good and which should be
tested+applied. The consequence for this patchset would be that patch 2 should
be completely dropped and instead the tp_meter should become its own command
in the netlink interface of batman-adv. Any opinions about that (order in
which patches should be applied/netlink interface should be handled) by the
Simon, Antonio, Marek, Matthias or Andrew?
Antonio Quartulli (4):
batman-adv: return netdev status in the TX path
batman-adv: use another ICMP packet when sending command from userspace
batman-adv: throughput meter implementation
batctl: introduce throughput meter support
net/batman-adv/Makefile | 1 +
net/batman-adv/fragmentation.c | 41 +-
net/batman-adv/fragmentation.h | 6 +-
net/batman-adv/icmp_socket.c | 225 +++---
net/batman-adv/icmp_socket.h | 5 +-
net/batman-adv/main.c | 6 +-
net/batman-adv/main.h | 24 +-
net/batman-adv/packet.h | 120 ++++
net/batman-adv/routing.c | 33 +-
net/batman-adv/send.c | 25 +-
net/batman-adv/soft-interface.c | 2 +
net/batman-adv/tp_meter.c | 1453 +++++++++++++++++++++++++++++++++++++++
net/batman-adv/tp_meter.h | 34 +
net/batman-adv/types.h | 113 +++
14 files changed, 1944 insertions(+), 144 deletions(-)
Makefile | 2 +-
main.c | 6 ++
main.h | 1 +
man/batctl.8 | 24 +++++-
packet.h | 120 ++++++++++++++++++++++++++++++
tcpdump.c | 14 +++-
tp_meter.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tp_meter.h | 22 ++++++
8 files changed, 421 insertions(+), 4 deletions(-)
Kind regards,
Sven
From: Antonio Quartulli <antonio.quartulli(a)open-mesh.com>
Return the proper netdev TX status along the TX path so that the tp_meter
can understand when the queue is full and should stop sending packets.
Signed-off-by: Antonio Quartulli <antonio.quartulli(a)open-mesh.com>
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)open-mesh.com>
---
v2:
- Rebase on current master version
net/batman-adv/fragmentation.c | 41 +++++++++++++++++++++++++----------------
net/batman-adv/fragmentation.h | 6 +++---
net/batman-adv/main.c | 4 +++-
net/batman-adv/routing.c | 24 ++++++++++++++----------
net/batman-adv/send.c | 25 +++++++++++++------------
5 files changed, 58 insertions(+), 42 deletions(-)
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index 65536db..4cb7da2 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -434,11 +434,12 @@ err:
* @orig_node: final destination of the created fragments
* @neigh_node: next-hop of the created fragments
*
- * Return: true on success, false otherwise.
+ * Return: the netdev tx status or -1 in case of error.
+ * When -1 is returned the skb is not consumed.
*/
-bool batadv_frag_send_packet(struct sk_buff *skb,
- struct batadv_orig_node *orig_node,
- struct batadv_neigh_node *neigh_node)
+int 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 = NULL;
@@ -447,7 +448,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;
unsigned int header_size = sizeof(frag_header);
unsigned int max_fragment_size, max_packet_size;
- bool ret = false;
+ int ret = -1;
/* To avoid merge and refragmentation at next-hops we never send
* fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@@ -458,12 +459,12 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
/* Don't even try to fragment, if we need more than 16 fragments */
if (skb->len > max_packet_size)
- goto out_err;
+ goto out;
bat_priv = orig_node->bat_priv;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
- goto out_err;
+ goto out;
/* Create one header to be copied to all fragments */
frag_header.packet_type = BATADV_UNICAST_FRAG;
@@ -480,23 +481,33 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
while (skb->len > max_fragment_size) {
skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
if (!skb_fragment)
- goto out_err;
+ goto out;
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_unicast_skb(skb_fragment, neigh_node);
+ ret = batadv_send_unicast_skb(skb_fragment, neigh_node);
+ if (ret != NET_XMIT_SUCCESS) {
+ /* return -1 so that the caller can free the original
+ * skb
+ */
+ ret = -1;
+ goto out;
+ }
+
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;
+ if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
+ ret = -1;
+ goto out;
+ }
}
/* 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;
+ goto out;
memcpy(skb->data, &frag_header, header_size);
@@ -504,11 +515,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
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_unicast_skb(skb, neigh_node);
+ ret = batadv_send_unicast_skb(skb, neigh_node);
- ret = true;
-
-out_err:
+out:
if (primary_if)
batadv_hardif_put(primary_if);
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
index 9ff77c7..3202fe3 100644
--- a/net/batman-adv/fragmentation.h
+++ b/net/batman-adv/fragmentation.h
@@ -34,9 +34,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);
+int 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/main.c b/net/batman-adv/main.c
index c8d8bc7..fff51ad 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -1195,6 +1195,7 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
unsigned char *tvlv_buff;
unsigned int tvlv_len;
ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
+ int res;
orig_node = batadv_orig_hash_find(bat_priv, dst);
if (!orig_node)
@@ -1227,7 +1228,8 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
tvlv_buff += sizeof(*tvlv_hdr);
memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ if (!(res != -1 && dev_xmit_complete(res)))
kfree_skb(skb);
out:
batadv_orig_node_put(orig_node);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 94b4356..fb0e5d6 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -268,7 +268,10 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmph->ttl = BATADV_TTL;
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res != NET_XMIT_DROP)
+ if (res == -1)
+ goto out;
+
+ if (dev_xmit_complete(res))
ret = NET_RX_SUCCESS;
break;
@@ -290,7 +293,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL;
struct batadv_icmp_packet *icmp_packet;
- int ret = NET_RX_DROP;
+ int res, ret = NET_RX_DROP;
icmp_packet = (struct batadv_icmp_packet *)skb->data;
@@ -321,7 +324,8 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
icmp_packet->ttl = BATADV_TTL;
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ if (res != -1 && dev_xmit_complete(res))
ret = NET_RX_SUCCESS;
out:
@@ -341,7 +345,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
struct ethhdr *ethhdr;
struct batadv_orig_node *orig_node = NULL;
int hdr_size = sizeof(struct batadv_icmp_header);
- int ret = NET_RX_DROP;
+ int res, ret = NET_RX_DROP;
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
@@ -407,7 +411,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmph->ttl--;
/* route it */
- if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
+ if (res != -1 && dev_xmit_complete(res))
ret = NET_RX_SUCCESS;
out:
@@ -642,6 +647,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
batadv_skb_set_priority(skb, hdr_len);
res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
+ if (res == -1)
+ goto out;
/* translate transmit result into receive result */
if (res == NET_XMIT_SUCCESS) {
@@ -649,12 +656,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
skb->len + ETH_HLEN);
-
- ret = NET_RX_SUCCESS;
- } else if (res == NET_XMIT_POLICED) {
- /* skb was buffered and consumed */
- ret = NET_RX_SUCCESS;
}
+ if (dev_xmit_complete(res))
+ ret = NET_RX_SUCCESS;
out:
if (orig_node)
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 724bd6e..d2713ca 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -155,8 +155,11 @@ int batadv_send_unicast_skb(struct sk_buff *skb,
* host, NULL can be passed as recv_if and no interface alternating is
* attempted.
*
- * Return: NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or
- * NET_XMIT_POLICED if the skb is buffered for later transmit.
+ * Return: -1 on failure (and the skb is not consumed), NET_XMIT_POLICED if the
+ * skb is buffered for later transmit or the NET_XMIT status returned by the
+ * lower routine if the packet has been passed down.
+ *
+ * If the returning value is not -1 the skb has been consumed.
*/
int batadv_send_skb_to_orig(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
@@ -164,7 +167,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
{
struct batadv_priv *bat_priv = orig_node->bat_priv;
struct batadv_neigh_node *neigh_node;
- int ret = NET_XMIT_DROP;
+ int ret = -1;
/* batadv_find_router() increases neigh_nodes refcount if found. */
neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
@@ -177,8 +180,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
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;
+ ret = batadv_frag_send_packet(skb, orig_node, neigh_node);
goto out;
}
@@ -187,12 +189,10 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
* (i.e. being forwarded). If the packet originates from this node or if
* network coding fails, then send the packet as usual.
*/
- if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) {
+ if (recv_if && batadv_nc_skb_forward(skb, neigh_node))
ret = NET_XMIT_POLICED;
- } else {
- batadv_send_unicast_skb(skb, neigh_node);
- ret = NET_XMIT_SUCCESS;
- }
+ else
+ ret = batadv_send_unicast_skb(skb, neigh_node);
out:
if (neigh_node)
@@ -318,7 +318,7 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
{
struct batadv_unicast_packet *unicast_packet;
struct ethhdr *ethhdr;
- int ret = NET_XMIT_DROP;
+ int res, ret = NET_XMIT_DROP;
if (!orig_node)
goto out;
@@ -355,7 +355,8 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
unicast_packet->ttvn = unicast_packet->ttvn - 1;
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ if (res != -1 && dev_xmit_complete(res))
ret = NET_XMIT_SUCCESS;
out:
--
2.8.0.rc3
From: Antonio Quartulli <antonio.quartulli(a)open-mesh.com>
Return the proper netdev TX status along the TX path so that the tp_meter
can understand when the queue is full and should stop sending packets.
Signed-off-by: Antonio Quartulli <antonio.quartulli(a)open-mesh.com>
Signed-off-by: Sven Eckelmann <sven.eckelmann(a)open-mesh.com>
---
v3:
- Rebase on current master version
- inform batctl about problems finding the remote originator
v2:
- Rebase on current master version
---
net/batman-adv/fragmentation.c | 41 +++++++++++++++++++++++++----------------
net/batman-adv/fragmentation.h | 6 +++---
net/batman-adv/main.c | 4 +++-
net/batman-adv/routing.c | 24 ++++++++++++++----------
net/batman-adv/send.c | 25 +++++++++++++------------
5 files changed, 58 insertions(+), 42 deletions(-)
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index 65536db..4cb7da2 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -434,11 +434,12 @@ err:
* @orig_node: final destination of the created fragments
* @neigh_node: next-hop of the created fragments
*
- * Return: true on success, false otherwise.
+ * Return: the netdev tx status or -1 in case of error.
+ * When -1 is returned the skb is not consumed.
*/
-bool batadv_frag_send_packet(struct sk_buff *skb,
- struct batadv_orig_node *orig_node,
- struct batadv_neigh_node *neigh_node)
+int 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 = NULL;
@@ -447,7 +448,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;
unsigned int header_size = sizeof(frag_header);
unsigned int max_fragment_size, max_packet_size;
- bool ret = false;
+ int ret = -1;
/* To avoid merge and refragmentation at next-hops we never send
* fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@@ -458,12 +459,12 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
/* Don't even try to fragment, if we need more than 16 fragments */
if (skb->len > max_packet_size)
- goto out_err;
+ goto out;
bat_priv = orig_node->bat_priv;
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if)
- goto out_err;
+ goto out;
/* Create one header to be copied to all fragments */
frag_header.packet_type = BATADV_UNICAST_FRAG;
@@ -480,23 +481,33 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
while (skb->len > max_fragment_size) {
skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
if (!skb_fragment)
- goto out_err;
+ goto out;
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_unicast_skb(skb_fragment, neigh_node);
+ ret = batadv_send_unicast_skb(skb_fragment, neigh_node);
+ if (ret != NET_XMIT_SUCCESS) {
+ /* return -1 so that the caller can free the original
+ * skb
+ */
+ ret = -1;
+ goto out;
+ }
+
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;
+ if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
+ ret = -1;
+ goto out;
+ }
}
/* 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;
+ goto out;
memcpy(skb->data, &frag_header, header_size);
@@ -504,11 +515,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
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_unicast_skb(skb, neigh_node);
+ ret = batadv_send_unicast_skb(skb, neigh_node);
- ret = true;
-
-out_err:
+out:
if (primary_if)
batadv_hardif_put(primary_if);
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
index 9ff77c7..3202fe3 100644
--- a/net/batman-adv/fragmentation.h
+++ b/net/batman-adv/fragmentation.h
@@ -34,9 +34,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);
+int 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/main.c b/net/batman-adv/main.c
index 5f2974b..1d6984a 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -1193,6 +1193,7 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
unsigned char *tvlv_buff;
unsigned int tvlv_len;
ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
+ int res;
orig_node = batadv_orig_hash_find(bat_priv, dst);
if (!orig_node)
@@ -1225,7 +1226,8 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
tvlv_buff += sizeof(*tvlv_hdr);
memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ if (!(res != -1 && dev_xmit_complete(res)))
kfree_skb(skb);
out:
batadv_orig_node_put(orig_node);
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index ae850f2..1c3fea0 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -268,7 +268,10 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
icmph->ttl = BATADV_TTL;
res = batadv_send_skb_to_orig(skb, orig_node, NULL);
- if (res != NET_XMIT_DROP)
+ if (res == -1)
+ goto out;
+
+ if (dev_xmit_complete(res))
ret = NET_RX_SUCCESS;
break;
@@ -290,7 +293,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if = NULL;
struct batadv_orig_node *orig_node = NULL;
struct batadv_icmp_packet *icmp_packet;
- int ret = NET_RX_DROP;
+ int res, ret = NET_RX_DROP;
icmp_packet = (struct batadv_icmp_packet *)skb->data;
@@ -321,7 +324,8 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
icmp_packet->ttl = BATADV_TTL;
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ if (res != -1 && dev_xmit_complete(res))
ret = NET_RX_SUCCESS;
out:
@@ -341,7 +345,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
struct ethhdr *ethhdr;
struct batadv_orig_node *orig_node = NULL;
int hdr_size = sizeof(struct batadv_icmp_header);
- int ret = NET_RX_DROP;
+ int res, ret = NET_RX_DROP;
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
@@ -407,7 +411,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
icmph->ttl--;
/* route it */
- if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
+ if (res != -1 && dev_xmit_complete(res))
ret = NET_RX_SUCCESS;
out:
@@ -642,6 +647,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
batadv_skb_set_priority(skb, hdr_len);
res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
+ if (res == -1)
+ goto out;
/* translate transmit result into receive result */
if (res == NET_XMIT_SUCCESS) {
@@ -649,12 +656,9 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
skb->len + ETH_HLEN);
-
- ret = NET_RX_SUCCESS;
- } else if (res == NET_XMIT_POLICED) {
- /* skb was buffered and consumed */
- ret = NET_RX_SUCCESS;
}
+ if (dev_xmit_complete(res))
+ ret = NET_RX_SUCCESS;
out:
if (orig_node)
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index f2f1256..e9b30d6 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -155,8 +155,11 @@ int batadv_send_unicast_skb(struct sk_buff *skb,
* host, NULL can be passed as recv_if and no interface alternating is
* attempted.
*
- * Return: NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or
- * NET_XMIT_POLICED if the skb is buffered for later transmit.
+ * Return: -1 on failure (and the skb is not consumed), NET_XMIT_POLICED if the
+ * skb is buffered for later transmit or the NET_XMIT status returned by the
+ * lower routine if the packet has been passed down.
+ *
+ * If the returning value is not -1 the skb has been consumed.
*/
int batadv_send_skb_to_orig(struct sk_buff *skb,
struct batadv_orig_node *orig_node,
@@ -164,7 +167,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
{
struct batadv_priv *bat_priv = orig_node->bat_priv;
struct batadv_neigh_node *neigh_node;
- int ret = NET_XMIT_DROP;
+ int ret = -1;
/* batadv_find_router() increases neigh_nodes refcount if found. */
neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
@@ -177,8 +180,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
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;
+ ret = batadv_frag_send_packet(skb, orig_node, neigh_node);
goto out;
}
@@ -187,12 +189,10 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
* (i.e. being forwarded). If the packet originates from this node or if
* network coding fails, then send the packet as usual.
*/
- if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) {
+ if (recv_if && batadv_nc_skb_forward(skb, neigh_node))
ret = NET_XMIT_POLICED;
- } else {
- batadv_send_unicast_skb(skb, neigh_node);
- ret = NET_XMIT_SUCCESS;
- }
+ else
+ ret = batadv_send_unicast_skb(skb, neigh_node);
out:
if (neigh_node)
@@ -318,7 +318,7 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
{
struct batadv_unicast_packet *unicast_packet;
struct ethhdr *ethhdr;
- int ret = NET_XMIT_DROP;
+ int res, ret = NET_XMIT_DROP;
if (!orig_node)
goto out;
@@ -355,7 +355,8 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
unicast_packet->ttvn = unicast_packet->ttvn - 1;
- if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP)
+ res = batadv_send_skb_to_orig(skb, orig_node, NULL);
+ if (res != -1 && dev_xmit_complete(res))
ret = NET_XMIT_SUCCESS;
out:
--
2.8.1
Based on top of Sven's last kref patchset.
Patch is untested, so would be great if Martin could verify that it at
least fixes some log spam.
If yes, not sure whether it is worth for maint though.
Cheers, Linus
This patchset completes netns support, by disabling debugfs entries
when not in the default name space, and correctly handling interface
stack loops when the parent is in a different name space.
It additionally adds netlink support for most of the information found
in debugfs, and is netns awaire.
Note: BLA is untested, so best assume it is broken...
v3:
* Fix the compat with older kernels. It now at least compiles with
3.18.32. I've not booted it though.
* Add missing kerneldoc
v2:
All changes requested by Sven:
* Added lots of missing includes and structure forward declarations
* Add two kernel doc comments
* Fixed an obvious bug in BLA, but it is probably still broken...
* Merged in the compat code Sven suggested. Only compile tested with 4.5.0
*** BLURB HERE ***
Andrew Lunn (7):
batman-adv: Handle parent interfaces in a different netns
batman-adv: compat.h: Add workaround for get_link_net()
batman-adv: Suppress debugfs entries for netns's
batman-adv: compat: Workarounds for previous patch
batman-adv: Indicate netlink socket can be used with netns.
batman-adv: add B.A.T.M.A.N. Dump gateways via netlink
batman-adv: add B.A.T.M.A.N. Dump BLA claims via netlink
Matthias Schiffer (5):
batman-adv: add generic netlink query API to replace debugfs files
batman-adv: netlink: add translation table query
batman-adv: netlink: add originator and neighbor table queries
batman-adv: add B.A.T.M.A.N. IV bat_{orig, neigh}_dump implementations
batman-adv: add B.A.T.M.A.N. V bat_{orig, neigh}_dump implementations
Makefile | 1 +
compat-include/linux/netlink.h | 45 +++++
compat-include/net/genetlink.h | 34 ++++
compat.h | 13 ++
include/uapi/linux/batman_adv.h | 111 ++++++++++++
net/batman-adv/Makefile | 1 +
net/batman-adv/bat_iv_ogm.c | 271 +++++++++++++++++++++++++++++
net/batman-adv/bat_v.c | 257 +++++++++++++++++++++++++++
net/batman-adv/bridge_loop_avoidance.c | 166 ++++++++++++++++++
net/batman-adv/bridge_loop_avoidance.h | 10 +-
net/batman-adv/debugfs.c | 18 ++
net/batman-adv/gateway_client.c | 131 ++++++++++++++
net/batman-adv/gateway_client.h | 2 +
net/batman-adv/hard-interface.c | 50 +++++-
net/batman-adv/main.c | 51 ++++++
net/batman-adv/main.h | 2 +
net/batman-adv/netlink.c | 302 ++++++++++++++++++++++++++++++++
net/batman-adv/netlink.h | 41 +++++
net/batman-adv/originator.c | 160 +++++++++++++++++
net/batman-adv/originator.h | 4 +
net/batman-adv/packet.h | 36 ----
net/batman-adv/translation-table.c | 308 +++++++++++++++++++++++++++++++++
net/batman-adv/translation-table.h | 4 +
net/batman-adv/types.h | 9 +
24 files changed, 1983 insertions(+), 44 deletions(-)
create mode 100644 compat-include/linux/netlink.h
create mode 100644 compat-include/net/genetlink.h
create mode 100644 include/uapi/linux/batman_adv.h
create mode 100644 net/batman-adv/netlink.c
create mode 100644 net/batman-adv/netlink.h
--
2.8.0.rc3