Bug 274028 - ng_bridge fails to learn MAC addresses if link is in different VNET
Summary: ng_bridge fails to learn MAC addresses if link is in different VNET
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 13.2-STABLE
Hardware: Any Any
: --- Affects Some People
Assignee: Marko Zec
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-09-22 15:54 UTC by Dancho Penev
Modified: 2024-01-08 05:27 UTC (History)
2 users (show)

See Also:
linimon: mfc-stable13?


Attachments
Switch VNETs when injecting mbufs into netgraph (466 bytes, patch)
2023-09-23 09:02 UTC, Marko Zec
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dancho Penev 2023-09-22 15:54:35 UTC
In data receive method when MAC address save is requested a false assumption is made that "curthread" is in same VNET as node, which of course is not always true. For example eiface is attached to a bridge and moved to different VNET:

kldload ng_ether
ngctl -f - << EOF
mkpeer vtnet0: bridge lower uplink1
name vtnet0:lower switch0
mkpeer switch0: eiface link0 ether
EOF
jail -c path=/ vnet=new vnet.interface=ngeth0 persist host.hostname=test name=test exec.start="sh -c 'ifconfig ngeth0 inet 192.168.1.123/24; ifconfig ngeth0 up'"
jexec test ping -c 1 192.168.1.254
ngctl msg switch0: gettable
ngctl msg switch0: getstats 0

In this case failures are recorded as "memoryFailures".

Fix:
--- a/sys/netgraph/ng_bridge.c
+++ b/sys/netgraph/ng_bridge.c
@@ -911,8 +911,10 @@ ng_bridge_rcvdata(hook_p hook, item_p item)
                strncpy(mh->hook, NG_HOOK_NAME(ctx.incoming->hook),
                    sizeof(mh->hook));
                memcpy(mh->addr, eh->ether_shost, sizeof(mh->addr));
+               CURVNET_SET(node->nd_vnet);
                NG_SEND_MSG_ID(error, node, msg, NG_NODE_ID(node),
                    NG_NODE_ID(node));
+               CURVNET_RESTORE();
                if (error)
                        counter_u64_add(ctx.incoming->stats.memoryFailures, 1);
        }
Comment 1 Marko Zec freebsd_committer freebsd_triage 2023-09-23 09:02:20 UTC
Created attachment 245156 [details]
Switch VNETs when injecting mbufs into netgraph

Good catch, thanks!  However, the culprit here is not ng_bridge, but ng_eiface, whic may be on lease to another vnet, while it remains bonded to its origin vnet on the netgraph layer.  In such circumstances, when injecting mbufs into netgraph, ng_eiface should switch curvnet to that of the netgraph layer, which it fails to.  For the problem at hand, the attached patch would be a more accurate fix, since it cures the cause, not the symptom.
Comment 2 commit-hook freebsd_committer freebsd_triage 2023-09-23 09:25:04 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=03ef737c544d3dd90a0000c18382db99ccf2ee9a

commit 03ef737c544d3dd90a0000c18382db99ccf2ee9a
Author:     Marko Zec <zec@FreeBSD.org>
AuthorDate: 2023-09-23 08:56:56 +0000
Commit:     Marko Zec <zec@FreeBSD.org>
CommitDate: 2023-09-23 08:56:56 +0000

    ng_eiface: switch VNETs when injecting mbufs into netgraph

    A ng_eiface instance may be on lease to a different vnet while
    remaining tied to its parent vnet.  In such circumstances, before
    injecting mbufs into netgraph, curvnet must be set to that of the
    ng_eiface's netgraph node.  Mark the vnet transition as QUIET,
    since otherwise it would be recorded as a curvnet recursion when
    ng_eiface's ifnet resides in the same (parent) vnet as its
    netgraph node.

    PR:             274028
    Reported by:    Dancho Penev <dpslavov@hotmail.com>
    MFC after:      1 week

 sys/netgraph/ng_eiface.c | 2 ++
 1 file changed, 2 insertions(+)
Comment 3 Dancho Penev 2023-09-23 12:00:43 UTC
Hi Marko,

Thank you for your swift response.
When I was thinking how to fix my problem I also considered your solution but went with more limited change instead of global one because:

a) I'm not expert here and it's silly to make broad changes in such situation
b) I would create hidden security catch: when someone moves interface into new VNET he/she expects outbound packets to be processed in this new VNET, instead behind the scene the VNET is replaced

That's why I thought that it's better to leave the global solution to more knowledgeable person, which definitely you are.
Comment 4 Graham Perrin 2023-09-23 16:21:31 UTC
^Triage: assign to the resolving committer.
Comment 5 Mark Linimon freebsd_committer freebsd_triage 2024-01-08 05:27:42 UTC
^Triage: set flag for possible MFC to 13.