aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLutz Donnerhacke <donner@FreeBSD.org>2021-04-27 07:49:50 +0000
committerLutz Donnerhacke <donner@FreeBSD.org>2021-05-20 05:58:30 +0000
commit1165cafa0baee55a46459e4cf7c2573ca25a0a1c (patch)
tree64fe40beff06bc80acaeb61c1be75ba3b757f3ce
parent80e3f1df8ca8d355b31f1b7596e025edb3a2746d (diff)
downloadsrc-1165cafa0baee55a46459e4cf7c2573ca25a0a1c.tar.gz
src-1165cafa0baee55a46459e4cf7c2573ca25a0a1c.zip
netgraph/ng_bridge: Handle send errors during loop handling
If sending out a packet fails during the loop over all links, the allocated memory is leaked and not all links receive a copy. This patch fixes those problems, clarifies a premature abort of the loop, and fixes a minory style(9) bug. PR: 255430 Submitted by: Dancho Penev Tested by: Dancho Penev Differential Revision: https://reviews.freebsd.org/D30008 (cherry picked from commit a56e5ad6903037861457da754574b4903dcb0e7e)
-rw-r--r--sys/netgraph/ng_bridge.c57
1 files changed, 31 insertions, 26 deletions
diff --git a/sys/netgraph/ng_bridge.c b/sys/netgraph/ng_bridge.c
index 5917c1084527..3243319c99e8 100644
--- a/sys/netgraph/ng_bridge.c
+++ b/sys/netgraph/ng_bridge.c
@@ -707,22 +707,28 @@ ng_bridge_send_data(link_cp dst, int manycast, struct mbuf *m, item_p item) {
else
NG_SEND_DATA_ONLY(error, dst->hook, m);
- if (error == 0) {
- counter_u64_add(dst->stats.xmitPackets, 1);
- counter_u64_add(dst->stats.xmitOctets, len);
- switch (manycast) {
- default: /* unknown unicast */
- break;
- case 1: /* multicast */
- counter_u64_add(dst->stats.xmitMulticasts, 1);
- break;
- case 2: /* broadcast */
- counter_u64_add(dst->stats.xmitBroadcasts, 1);
- break;
- }
+ if (error) {
+ /* The packet is still ours */
+ if (item != NULL)
+ NG_FREE_ITEM(item);
+ if (m != NULL)
+ NG_FREE_M(m);
+ return (error);
}
- return (error);
+ counter_u64_add(dst->stats.xmitPackets, 1);
+ counter_u64_add(dst->stats.xmitOctets, len);
+ switch (manycast) {
+ default: /* unknown unicast */
+ break;
+ case 1: /* multicast */
+ counter_u64_add(dst->stats.xmitMulticasts, 1);
+ break;
+ case 2: /* broadcast */
+ counter_u64_add(dst->stats.xmitBroadcasts, 1);
+ break;
+ }
+ return (0);
}
/*
@@ -760,16 +766,16 @@ ng_bridge_send_ctx(hook_p dst, void *arg)
* It's usable link but not the reserved (first) one.
* Copy mbuf info for sending.
*/
- m2 = m_dup(ctx->m, M_NOWAIT); /* XXX m_copypacket() */
+ m2 = m_dup(ctx->m, M_NOWAIT);
if (m2 == NULL) {
counter_u64_add(ctx->incoming->stats.memoryFailures, 1);
ctx->error = ENOBUFS;
- return (0); /* abort loop */
+ return (0); /* abort loop, do not try again and again */
}
/* Send packet */
error = ng_bridge_send_data(destLink, ctx->manycast, m2, NULL);
- if(error)
+ if (error)
ctx->error = error;
return (1);
}
@@ -922,18 +928,17 @@ ng_bridge_rcvdata(hook_p hook, item_p item)
/* Distribute unknown, multicast, broadcast pkts to all other links */
NG_NODE_FOREACH_HOOK(node, ng_bridge_send_ctx, &ctx, ret);
- /* If we never saw a good link, leave. */
- if (ctx.foundFirst == NULL || ctx.error != 0) {
+ /* Finally send out on the first link found */
+ if (ctx.foundFirst != NULL) {
+ int error = ng_bridge_send_data(ctx.foundFirst, ctx.manycast, ctx.m, item);
+ if (error)
+ ctx.error = error;
+ } else { /* nothing to send at all */
NG_FREE_ITEM(item);
NG_FREE_M(ctx.m);
- return (ctx.error);
}
-
- /*
- * If we've sent all the others, send the original
- * on the first link we found.
- */
- return (ng_bridge_send_data(ctx.foundFirst, ctx.manycast, ctx.m, item));
+
+ return (ctx.error);
}
/*