aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv
diff options
context:
space:
mode:
authorAntonio Quartulli <antonio.quartulli@open-mesh.com>2016-05-18 05:38:48 -0400
committerSimon Wunderlich <sw@simonwunderlich.de>2016-07-04 06:37:18 -0400
commitf50ca95a691e9fd1fce530aade58c98d621cb1fe (patch)
tree8a44b847d9cdc89d92289db192e34977307df55c /net/batman-adv
parent5da0aef5e93591b373010c10f374c4161b37728c (diff)
batman-adv: return netdev status in the TX path
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@open-mesh.com> Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Diffstat (limited to 'net/batman-adv')
-rw-r--r--net/batman-adv/fragmentation.c41
-rw-r--r--net/batman-adv/fragmentation.h6
-rw-r--r--net/batman-adv/routing.c25
-rw-r--r--net/batman-adv/send.c36
-rw-r--r--net/batman-adv/tvlv.c4
5 files changed, 68 insertions, 44 deletions
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index 9f41a0a0d6ab..0934730fb7ff 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -433,11 +433,12 @@ err:
433 * @orig_node: final destination of the created fragments 433 * @orig_node: final destination of the created fragments
434 * @neigh_node: next-hop of the created fragments 434 * @neigh_node: next-hop of the created fragments
435 * 435 *
436 * Return: true on success, false otherwise. 436 * Return: the netdev tx status or -1 in case of error.
437 * When -1 is returned the skb is not consumed.
437 */ 438 */
438bool batadv_frag_send_packet(struct sk_buff *skb, 439int batadv_frag_send_packet(struct sk_buff *skb,
439 struct batadv_orig_node *orig_node, 440 struct batadv_orig_node *orig_node,
440 struct batadv_neigh_node *neigh_node) 441 struct batadv_neigh_node *neigh_node)
441{ 442{
442 struct batadv_priv *bat_priv; 443 struct batadv_priv *bat_priv;
443 struct batadv_hard_iface *primary_if = NULL; 444 struct batadv_hard_iface *primary_if = NULL;
@@ -446,7 +447,7 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
446 unsigned int mtu = neigh_node->if_incoming->net_dev->mtu; 447 unsigned int mtu = neigh_node->if_incoming->net_dev->mtu;
447 unsigned int header_size = sizeof(frag_header); 448 unsigned int header_size = sizeof(frag_header);
448 unsigned int max_fragment_size, max_packet_size; 449 unsigned int max_fragment_size, max_packet_size;
449 bool ret = false; 450 int ret = -1;
450 451
451 /* To avoid merge and refragmentation at next-hops we never send 452 /* To avoid merge and refragmentation at next-hops we never send
452 * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE 453 * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE
@@ -457,12 +458,12 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
457 458
458 /* Don't even try to fragment, if we need more than 16 fragments */ 459 /* Don't even try to fragment, if we need more than 16 fragments */
459 if (skb->len > max_packet_size) 460 if (skb->len > max_packet_size)
460 goto out_err; 461 goto out;
461 462
462 bat_priv = orig_node->bat_priv; 463 bat_priv = orig_node->bat_priv;
463 primary_if = batadv_primary_if_get_selected(bat_priv); 464 primary_if = batadv_primary_if_get_selected(bat_priv);
464 if (!primary_if) 465 if (!primary_if)
465 goto out_err; 466 goto out;
466 467
467 /* Create one header to be copied to all fragments */ 468 /* Create one header to be copied to all fragments */
468 frag_header.packet_type = BATADV_UNICAST_FRAG; 469 frag_header.packet_type = BATADV_UNICAST_FRAG;
@@ -488,23 +489,33 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
488 while (skb->len > max_fragment_size) { 489 while (skb->len > max_fragment_size) {
489 skb_fragment = batadv_frag_create(skb, &frag_header, mtu); 490 skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
490 if (!skb_fragment) 491 if (!skb_fragment)
491 goto out_err; 492 goto out;
492 493
493 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX); 494 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
494 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES, 495 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
495 skb_fragment->len + ETH_HLEN); 496 skb_fragment->len + ETH_HLEN);
496 batadv_send_unicast_skb(skb_fragment, neigh_node); 497 ret = batadv_send_unicast_skb(skb_fragment, neigh_node);
498 if (ret != NET_XMIT_SUCCESS) {
499 /* return -1 so that the caller can free the original
500 * skb
501 */
502 ret = -1;
503 goto out;
504 }
505
497 frag_header.no++; 506 frag_header.no++;
498 507
499 /* The initial check in this function should cover this case */ 508 /* The initial check in this function should cover this case */
500 if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) 509 if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
501 goto out_err; 510 ret = -1;
511 goto out;
512 }
502 } 513 }
503 514
504 /* Make room for the fragment header. */ 515 /* Make room for the fragment header. */
505 if (batadv_skb_head_push(skb, header_size) < 0 || 516 if (batadv_skb_head_push(skb, header_size) < 0 ||
506 pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0) 517 pskb_expand_head(skb, header_size + ETH_HLEN, 0, GFP_ATOMIC) < 0)
507 goto out_err; 518 goto out;
508 519
509 memcpy(skb->data, &frag_header, header_size); 520 memcpy(skb->data, &frag_header, header_size);
510 521
@@ -512,11 +523,9 @@ bool batadv_frag_send_packet(struct sk_buff *skb,
512 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX); 523 batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_TX);
513 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES, 524 batadv_add_counter(bat_priv, BATADV_CNT_FRAG_TX_BYTES,
514 skb->len + ETH_HLEN); 525 skb->len + ETH_HLEN);
515 batadv_send_unicast_skb(skb, neigh_node); 526 ret = batadv_send_unicast_skb(skb, neigh_node);
516 527
517 ret = true; 528out:
518
519out_err:
520 if (primary_if) 529 if (primary_if)
521 batadv_hardif_put(primary_if); 530 batadv_hardif_put(primary_if);
522 531
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
index 9ff77c7ef7c7..3202fe329e63 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,
34 struct batadv_orig_node *orig_node_src); 34 struct batadv_orig_node *orig_node_src);
35bool batadv_frag_skb_buffer(struct sk_buff **skb, 35bool batadv_frag_skb_buffer(struct sk_buff **skb,
36 struct batadv_orig_node *orig_node); 36 struct batadv_orig_node *orig_node);
37bool batadv_frag_send_packet(struct sk_buff *skb, 37int batadv_frag_send_packet(struct sk_buff *skb,
38 struct batadv_orig_node *orig_node, 38 struct batadv_orig_node *orig_node,
39 struct batadv_neigh_node *neigh_node); 39 struct batadv_neigh_node *neigh_node);
40 40
41/** 41/**
42 * batadv_frag_check_entry - check if a list of fragments has timed out 42 * batadv_frag_check_entry - check if a list of fragments has timed out
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 5833ab3008a1..76de583fe866 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -270,8 +270,10 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
270 icmph->ttl = BATADV_TTL; 270 icmph->ttl = BATADV_TTL;
271 271
272 res = batadv_send_skb_to_orig(skb, orig_node, NULL); 272 res = batadv_send_skb_to_orig(skb, orig_node, NULL);
273 if (res != NET_XMIT_DROP) 273 if (res == -1)
274 ret = NET_RX_SUCCESS; 274 goto out;
275
276 ret = NET_RX_SUCCESS;
275 277
276 break; 278 break;
277 default: 279 default:
@@ -292,7 +294,7 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
292 struct batadv_hard_iface *primary_if = NULL; 294 struct batadv_hard_iface *primary_if = NULL;
293 struct batadv_orig_node *orig_node = NULL; 295 struct batadv_orig_node *orig_node = NULL;
294 struct batadv_icmp_packet *icmp_packet; 296 struct batadv_icmp_packet *icmp_packet;
295 int ret = NET_RX_DROP; 297 int res, ret = NET_RX_DROP;
296 298
297 icmp_packet = (struct batadv_icmp_packet *)skb->data; 299 icmp_packet = (struct batadv_icmp_packet *)skb->data;
298 300
@@ -323,7 +325,8 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
323 icmp_packet->msg_type = BATADV_TTL_EXCEEDED; 325 icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
324 icmp_packet->ttl = BATADV_TTL; 326 icmp_packet->ttl = BATADV_TTL;
325 327
326 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 328 res = batadv_send_skb_to_orig(skb, orig_node, NULL);
329 if (res != -1)
327 ret = NET_RX_SUCCESS; 330 ret = NET_RX_SUCCESS;
328 331
329out: 332out:
@@ -343,7 +346,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
343 struct ethhdr *ethhdr; 346 struct ethhdr *ethhdr;
344 struct batadv_orig_node *orig_node = NULL; 347 struct batadv_orig_node *orig_node = NULL;
345 int hdr_size = sizeof(struct batadv_icmp_header); 348 int hdr_size = sizeof(struct batadv_icmp_header);
346 int ret = NET_RX_DROP; 349 int res, ret = NET_RX_DROP;
347 350
348 /* drop packet if it has not necessary minimum size */ 351 /* drop packet if it has not necessary minimum size */
349 if (unlikely(!pskb_may_pull(skb, hdr_size))) 352 if (unlikely(!pskb_may_pull(skb, hdr_size)))
@@ -409,7 +412,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
409 icmph->ttl--; 412 icmph->ttl--;
410 413
411 /* route it */ 414 /* route it */
412 if (batadv_send_skb_to_orig(skb, orig_node, recv_if) != NET_XMIT_DROP) 415 res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
416 if (res != -1)
413 ret = NET_RX_SUCCESS; 417 ret = NET_RX_SUCCESS;
414 418
415out: 419out:
@@ -646,6 +650,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
646 650
647 len = skb->len; 651 len = skb->len;
648 res = batadv_send_skb_to_orig(skb, orig_node, recv_if); 652 res = batadv_send_skb_to_orig(skb, orig_node, recv_if);
653 if (res == -1)
654 goto out;
649 655
650 /* translate transmit result into receive result */ 656 /* translate transmit result into receive result */
651 if (res == NET_XMIT_SUCCESS) { 657 if (res == NET_XMIT_SUCCESS) {
@@ -653,13 +659,10 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
653 batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD); 659 batadv_inc_counter(bat_priv, BATADV_CNT_FORWARD);
654 batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES, 660 batadv_add_counter(bat_priv, BATADV_CNT_FORWARD_BYTES,
655 len + ETH_HLEN); 661 len + ETH_HLEN);
656
657 ret = NET_RX_SUCCESS;
658 } else if (res == -EINPROGRESS) {
659 /* skb was buffered and consumed */
660 ret = NET_RX_SUCCESS;
661 } 662 }
662 663
664 ret = NET_RX_SUCCESS;
665
663out: 666out:
664 if (orig_node) 667 if (orig_node)
665 batadv_orig_node_put(orig_node); 668 batadv_orig_node_put(orig_node);
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 3a59df26ee32..3a10d87b4b76 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -20,6 +20,7 @@
20 20
21#include <linux/atomic.h> 21#include <linux/atomic.h>
22#include <linux/byteorder/generic.h> 22#include <linux/byteorder/generic.h>
23#include <linux/errno.h>
23#include <linux/etherdevice.h> 24#include <linux/etherdevice.h>
24#include <linux/fs.h> 25#include <linux/fs.h>
25#include <linux/if.h> 26#include <linux/if.h>
@@ -72,6 +73,7 @@ int batadv_send_skb_packet(struct sk_buff *skb,
72{ 73{
73 struct batadv_priv *bat_priv; 74 struct batadv_priv *bat_priv;
74 struct ethhdr *ethhdr; 75 struct ethhdr *ethhdr;
76 int ret;
75 77
76 bat_priv = netdev_priv(hard_iface->soft_iface); 78 bat_priv = netdev_priv(hard_iface->soft_iface);
77 79
@@ -109,8 +111,15 @@ int batadv_send_skb_packet(struct sk_buff *skb,
109 /* dev_queue_xmit() returns a negative result on error. However on 111 /* dev_queue_xmit() returns a negative result on error. However on
110 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP 112 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
111 * (which is > 0). This will not be treated as an error. 113 * (which is > 0). This will not be treated as an error.
114 *
115 * a negative value cannot be returned because it could be interepreted
116 * as not consumed skb by callers of batadv_send_skb_to_orig.
112 */ 117 */
113 return dev_queue_xmit(skb); 118 ret = dev_queue_xmit(skb);
119 if (ret < 0)
120 ret = NET_XMIT_DROP;
121
122 return ret;
114send_skb_err: 123send_skb_err:
115 kfree_skb(skb); 124 kfree_skb(skb);
116 return NET_XMIT_DROP; 125 return NET_XMIT_DROP;
@@ -156,8 +165,11 @@ int batadv_send_unicast_skb(struct sk_buff *skb,
156 * host, NULL can be passed as recv_if and no interface alternating is 165 * host, NULL can be passed as recv_if and no interface alternating is
157 * attempted. 166 * attempted.
158 * 167 *
159 * Return: NET_XMIT_SUCCESS on success, NET_XMIT_DROP on failure, or 168 * Return: -1 on failure (and the skb is not consumed), -EINPROGRESS if the
160 * -EINPROGRESS if the skb is buffered for later transmit. 169 * skb is buffered for later transmit or the NET_XMIT status returned by the
170 * lower routine if the packet has been passed down.
171 *
172 * If the returning value is not -1 the skb has been consumed.
161 */ 173 */
162int batadv_send_skb_to_orig(struct sk_buff *skb, 174int batadv_send_skb_to_orig(struct sk_buff *skb,
163 struct batadv_orig_node *orig_node, 175 struct batadv_orig_node *orig_node,
@@ -165,7 +177,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
165{ 177{
166 struct batadv_priv *bat_priv = orig_node->bat_priv; 178 struct batadv_priv *bat_priv = orig_node->bat_priv;
167 struct batadv_neigh_node *neigh_node; 179 struct batadv_neigh_node *neigh_node;
168 int ret = NET_XMIT_DROP; 180 int ret = -1;
169 181
170 /* batadv_find_router() increases neigh_nodes refcount if found. */ 182 /* batadv_find_router() increases neigh_nodes refcount if found. */
171 neigh_node = batadv_find_router(bat_priv, orig_node, recv_if); 183 neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
@@ -178,8 +190,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
178 if (atomic_read(&bat_priv->fragmentation) && 190 if (atomic_read(&bat_priv->fragmentation) &&
179 skb->len > neigh_node->if_incoming->net_dev->mtu) { 191 skb->len > neigh_node->if_incoming->net_dev->mtu) {
180 /* Fragment and send packet. */ 192 /* Fragment and send packet. */
181 if (batadv_frag_send_packet(skb, orig_node, neigh_node)) 193 ret = batadv_frag_send_packet(skb, orig_node, neigh_node);
182 ret = NET_XMIT_SUCCESS;
183 194
184 goto out; 195 goto out;
185 } 196 }
@@ -188,12 +199,10 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
188 * (i.e. being forwarded). If the packet originates from this node or if 199 * (i.e. being forwarded). If the packet originates from this node or if
189 * network coding fails, then send the packet as usual. 200 * network coding fails, then send the packet as usual.
190 */ 201 */
191 if (recv_if && batadv_nc_skb_forward(skb, neigh_node)) { 202 if (recv_if && batadv_nc_skb_forward(skb, neigh_node))
192 ret = -EINPROGRESS; 203 ret = -EINPROGRESS;
193 } else { 204 else
194 batadv_send_unicast_skb(skb, neigh_node); 205 ret = batadv_send_unicast_skb(skb, neigh_node);
195 ret = NET_XMIT_SUCCESS;
196 }
197 206
198out: 207out:
199 if (neigh_node) 208 if (neigh_node)
@@ -319,7 +328,7 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
319{ 328{
320 struct batadv_unicast_packet *unicast_packet; 329 struct batadv_unicast_packet *unicast_packet;
321 struct ethhdr *ethhdr; 330 struct ethhdr *ethhdr;
322 int ret = NET_XMIT_DROP; 331 int res, ret = NET_XMIT_DROP;
323 332
324 if (!orig_node) 333 if (!orig_node)
325 goto out; 334 goto out;
@@ -356,7 +365,8 @@ int batadv_send_skb_unicast(struct batadv_priv *bat_priv,
356 if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) 365 if (batadv_tt_global_client_is_roaming(bat_priv, ethhdr->h_dest, vid))
357 unicast_packet->ttvn = unicast_packet->ttvn - 1; 366 unicast_packet->ttvn = unicast_packet->ttvn - 1;
358 367
359 if (batadv_send_skb_to_orig(skb, orig_node, NULL) != NET_XMIT_DROP) 368 res = batadv_send_skb_to_orig(skb, orig_node, NULL);
369 if (res != -1)
360 ret = NET_XMIT_SUCCESS; 370 ret = NET_XMIT_SUCCESS;
361 371
362out: 372out:
diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
index 2fd542e0d6a8..3d1cf0fb112d 100644
--- a/net/batman-adv/tvlv.c
+++ b/net/batman-adv/tvlv.c
@@ -591,6 +591,7 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
591 unsigned char *tvlv_buff; 591 unsigned char *tvlv_buff;
592 unsigned int tvlv_len; 592 unsigned int tvlv_len;
593 ssize_t hdr_len = sizeof(*unicast_tvlv_packet); 593 ssize_t hdr_len = sizeof(*unicast_tvlv_packet);
594 int res;
594 595
595 orig_node = batadv_orig_hash_find(bat_priv, dst); 596 orig_node = batadv_orig_hash_find(bat_priv, dst);
596 if (!orig_node) 597 if (!orig_node)
@@ -623,7 +624,8 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, u8 *src,
623 tvlv_buff += sizeof(*tvlv_hdr); 624 tvlv_buff += sizeof(*tvlv_hdr);
624 memcpy(tvlv_buff, tvlv_value, tvlv_value_len); 625 memcpy(tvlv_buff, tvlv_value, tvlv_value_len);
625 626
626 if (batadv_send_skb_to_orig(skb, orig_node, NULL) == NET_XMIT_DROP) 627 res = batadv_send_skb_to_orig(skb, orig_node, NULL);
628 if (res == -1)
627 kfree_skb(skb); 629 kfree_skb(skb);
628out: 630out:
629 batadv_orig_node_put(orig_node); 631 batadv_orig_node_put(orig_node);