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
MFC after:	1 week
Differential Revision: https://reviews.freebsd.org/D30008
This commit is contained in:
Lutz Donnerhacke 2021-04-27 09:49:50 +02:00
parent 4dfe70fdbd
commit a56e5ad690

View file

@ -663,22 +663,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);
}
/*
@ -716,16 +722,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);
}
@ -859,18 +865,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);
}
/*