diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c index d6c78c318dd..d37476bb716 100644 --- a/src/network/netdev/netdev.c +++ b/src/network/netdev/netdev.c @@ -203,6 +203,11 @@ NetDev* netdev_detach_name(NetDev *netdev, const char *name) { static NetDev* netdev_detach_impl(NetDev *netdev) { assert(netdev); + if (netdev->state != _NETDEV_STATE_INVALID && + NETDEV_VTABLE(netdev) && + NETDEV_VTABLE(netdev)->detach) + NETDEV_VTABLE(netdev)->detach(netdev); + NetDev *n = netdev_detach_name(netdev, netdev->ifname); netdev->manager = NULL; @@ -218,6 +223,8 @@ void netdev_detach(NetDev *netdev) { static NetDev* netdev_free(NetDev *netdev) { assert(netdev); + netdev_detach_impl(netdev); + /* Invoke the per-kind done() destructor, but only if the state field is initialized. We conditionalize that * because we parse .netdev files twice: once to determine the kind (with a short, minimal NetDev structure * allocation, with no room for per-kind fields), and once to read the kind's properties (with a full, @@ -230,8 +237,6 @@ static NetDev* netdev_free(NetDev *netdev) { NETDEV_VTABLE(netdev)->done) NETDEV_VTABLE(netdev)->done(netdev); - netdev_detach_impl(netdev); - condition_free_list(netdev->conditions); free(netdev->filename); strv_free(netdev->dropins); @@ -303,6 +308,12 @@ static int netdev_attach(NetDev *netdev) { if (r < 0) return r; + if (NETDEV_VTABLE(netdev)->attach) { + r = NETDEV_VTABLE(netdev)->attach(netdev); + if (r < 0) + return r; + } + return 0; } @@ -335,7 +346,10 @@ void link_assign_netdev(Link *link) { if (netdev_get(link->manager, link->ifname, &netdev) < 0) return; - if (netdev->ifindex != link->ifindex) + int ifindex = NETDEV_VTABLE(netdev)->get_ifindex ? + NETDEV_VTABLE(netdev)->get_ifindex(netdev, link->ifname) : + netdev->ifindex; + if (ifindex != link->ifindex) return; if (NETDEV_VTABLE(netdev)->iftype != link->iftype) @@ -426,6 +440,9 @@ static int netdev_set_ifindex_impl(NetDev *netdev, const char *name, int ifindex assert(name); assert(ifindex > 0); + if (NETDEV_VTABLE(netdev)->set_ifindex) + return NETDEV_VTABLE(netdev)->set_ifindex(netdev, name, ifindex); + if (!streq(netdev->ifname, name)) return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL), "Received netlink message with unexpected interface name %s (ifindex=%i).", diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h index 0b942caa4b4..10b9d0dd77a 100644 --- a/src/network/netdev/netdev.h +++ b/src/network/netdev/netdev.h @@ -169,6 +169,16 @@ typedef struct NetDevVTable { /* verify that compulsory configuration options were specified */ int (*config_verify)(NetDev *netdev, const char *filename); + /* attach/detach additional interfaces, e.g. veth peer or L2TP sessions. */ + int (*attach)(NetDev *netdev); + void (*detach)(NetDev *netdev); + + /* set ifindex of the created interface. */ + int (*set_ifindex)(NetDev *netdev, const char *name, int ifindex); + + /* get ifindex of the netdev. */ + int (*get_ifindex)(NetDev *netdev, const char *name); + /* expected iftype, e.g. ARPHRD_ETHER. */ uint16_t iftype;