Skip to content

Commit 401cbbb

Browse files
yangbolu1991fabiobaltieri
authored andcommitted
net: bridge: fix pkt management during forwarding
There were several problems of pkt management during forwarding. 1. No need to do net_pkt_ref/net_pkt_unref around net_if_queue_tx. 2. Finally when completed forwarding, there was a net_pkt_unref for pkt using cloning. However it also applied to pkt not using cloning. This was causing pkt was released before sending. 3. Whether pkt cloning used or not, should not be decided by bridge interfaces count. It's should be decided by interface count to forward. An example was sending pkt via bridge interface. If there were two interfaces attached to bridge, cloning was needed but current code won't. Signed-off-by: Yangbo Lu <[email protected]>
1 parent 1eb5c97 commit 401cbbb

File tree

1 file changed

+21
-21
lines changed

1 file changed

+21
-21
lines changed

subsys/net/l2/ethernet/bridge.c

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -339,27 +339,32 @@ static enum net_verdict bridge_iface_process(struct net_if *iface,
339339
{
340340
struct eth_bridge_iface_context *ctx = net_if_get_device(iface)->data;
341341
struct net_if *orig_iface;
342-
struct net_pkt *send_pkt;
343-
size_t count;
342+
struct net_pkt *send_pkt = pkt;
343+
int fwd_iface_num = 0;
344344

345345
/* Drop all link-local packets for now. */
346346
if (is_link_local_addr((struct net_eth_addr *)net_pkt_lladdr_dst(pkt))) {
347347
NET_DBG("DROP: lladdr");
348-
goto out;
348+
net_pkt_unref(pkt);
349+
return NET_OK;
349350
}
350351

351352
lock_bridge(ctx);
352353

353-
/* Keep the original packet interface so that we can send to each
354-
* bridged interface.
355-
*/
356354
orig_iface = net_pkt_orig_iface(pkt);
357355

358-
count = ctx->count;
356+
/* Get interface number to forward */
357+
ARRAY_FOR_EACH(ctx->eth_iface, i) {
358+
if (ctx->eth_iface[i] != NULL && ctx->eth_iface[i] != orig_iface) {
359+
/* Skip it if not up */
360+
if (!net_if_flag_is_set(ctx->eth_iface[i], NET_IF_UP)) {
361+
continue;
362+
}
363+
fwd_iface_num++;
364+
}
365+
}
359366

360-
/* Pass the data to all the Ethernet interface except the originator
361-
* Ethernet interface.
362-
*/
367+
/* Forward pkt to other interfaces */
363368
ARRAY_FOR_EACH(ctx->eth_iface, i) {
364369
if (ctx->eth_iface[i] != NULL && ctx->eth_iface[i] != orig_iface) {
365370
/* Skip it if not up */
@@ -370,16 +375,12 @@ static enum net_verdict bridge_iface_process(struct net_if *iface,
370375
/* Clone the packet if we have more than two interfaces in the bridge
371376
* because the first send might mess the data part of the message.
372377
*/
373-
if (count > 2) {
378+
if (fwd_iface_num > 1) {
374379
send_pkt = net_pkt_clone(pkt, K_NO_WAIT);
375380
if (send_pkt == NULL) {
376381
NET_DBG("DROP: clone failed");
377382
break;
378383
}
379-
380-
net_pkt_ref(send_pkt);
381-
} else {
382-
send_pkt = net_pkt_ref(pkt);
383384
}
384385

385386
net_pkt_set_family(send_pkt, AF_UNSPEC);
@@ -390,16 +391,15 @@ static enum net_verdict bridge_iface_process(struct net_if *iface,
390391
is_send ? "Send" : "Recv",
391392
net_if_get_by_iface(ctx->eth_iface[i]),
392393
send_pkt, (int)atomic_get(&send_pkt->atomic_ref));
393-
394-
net_pkt_unref(send_pkt);
395394
}
396395
}
397396

398-
unlock_bridge(ctx);
397+
/* Free pkt if cloned pkt is used to send */
398+
if (send_pkt != pkt) {
399+
net_pkt_unref(pkt);
400+
}
399401

400-
out:
401-
/* The packet was cloned by the caller so remove it here. */
402-
net_pkt_unref(pkt);
402+
unlock_bridge(ctx);
403403

404404
return NET_OK;
405405
}

0 commit comments

Comments
 (0)