/* forward declaration for rtnl_create_link() */
 static struct rtnl_link_ops vxcan_link_ops;
 
-static int vxcan_newlink(struct net *net, struct net_device *dev,
+static int vxcan_newlink(struct net *peer_net, struct net_device *dev,
                         struct nlattr *tb[], struct nlattr *data[],
                         struct netlink_ext_ack *extack)
 {
        struct vxcan_priv *priv;
        struct net_device *peer;
-       struct net *peer_net;
 
        struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb;
        char ifname[IFNAMSIZ];
                name_assign_type = NET_NAME_ENUM;
        }
 
-       peer_net = rtnl_link_get_net(net, tbp);
        peer = rtnl_create_link(peer_net, ifname, name_assign_type,
                                &vxcan_link_ops, tbp, extack);
-       if (IS_ERR(peer)) {
-               put_net(peer_net);
+       if (IS_ERR(peer))
                return PTR_ERR(peer);
-       }
 
        if (ifmp && dev->ifindex)
                peer->ifindex = ifmp->ifi_index;
 
        err = register_netdevice(peer);
-       put_net(peer_net);
-       peer_net = NULL;
        if (err < 0) {
                free_netdev(peer);
                return err;
 
 
 static struct rtnl_link_ops netkit_link_ops;
 
-static int netkit_new_link(struct net *src_net, struct net_device *dev,
+static int netkit_new_link(struct net *peer_net, struct net_device *dev,
                           struct nlattr *tb[], struct nlattr *data[],
                           struct netlink_ext_ack *extack)
 {
        struct net_device *peer;
        char ifname[IFNAMSIZ];
        struct netkit *nk;
-       struct net *net;
        int err;
 
        if (data) {
            (tb[IFLA_ADDRESS] || tbp[IFLA_ADDRESS]))
                return -EOPNOTSUPP;
 
-       net = rtnl_link_get_net(src_net, tbp);
-       peer = rtnl_create_link(net, ifname, ifname_assign_type,
+       peer = rtnl_create_link(peer_net, ifname, ifname_assign_type,
                                &netkit_link_ops, tbp, extack);
-       if (IS_ERR(peer)) {
-               put_net(net);
+       if (IS_ERR(peer))
                return PTR_ERR(peer);
-       }
 
        netif_inherit_tso_max(peer, dev);
 
        bpf_mprog_bundle_init(&nk->bundle);
 
        err = register_netdevice(peer);
-       put_net(net);
        if (err < 0)
                goto err_register_peer;
        netif_carrier_off(peer);
 
        return 0;
 }
 
-static int veth_newlink(struct net *src_net, struct net_device *dev,
+static int veth_newlink(struct net *peer_net, struct net_device *dev,
                        struct nlattr *tb[], struct nlattr *data[],
                        struct netlink_ext_ack *extack)
 {
        struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
        unsigned char name_assign_type;
        struct ifinfomsg *ifmp;
-       struct net *net;
 
        /*
         * create and register peer first
                name_assign_type = NET_NAME_ENUM;
        }
 
-       net = rtnl_link_get_net(src_net, tbp);
-       peer = rtnl_create_link(net, ifname, name_assign_type,
+       peer = rtnl_create_link(peer_net, ifname, name_assign_type,
                                &veth_link_ops, tbp, extack);
-       if (IS_ERR(peer)) {
-               put_net(net);
+       if (IS_ERR(peer))
                return PTR_ERR(peer);
-       }
 
        if (!ifmp || !tbp[IFLA_ADDRESS])
                eth_hw_addr_random(peer);
        netif_inherit_tso_max(peer, dev);
 
        err = register_netdevice(peer);
-       put_net(net);
-       net = NULL;
        if (err < 0)
                goto err_register_peer;
 
 
 static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
                               const struct rtnl_link_ops *ops,
                               struct net *tgt_net, struct net *link_net,
+                              struct net *peer_net,
                               const struct nlmsghdr *nlh,
                               struct nlattr **tb, struct nlattr **data,
                               struct netlink_ext_ack *extack)
 
        dev->ifindex = ifm->ifi_index;
 
+       if (link_net)
+               net = link_net;
+       if (peer_net)
+               net = peer_net;
+
        if (ops->newlink)
-               err = ops->newlink(link_net ? : net, dev, tb, data, extack);
+               err = ops->newlink(net, dev, tb, data, extack);
        else
                err = register_netdevice(dev);
        if (err < 0) {
        goto out;
 }
 
-static int rtnl_add_peer_net(struct rtnl_nets *rtnl_nets,
-                            const struct rtnl_link_ops *ops,
-                            struct nlattr *data[],
-                            struct netlink_ext_ack *extack)
+static struct net *rtnl_get_peer_net(const struct rtnl_link_ops *ops,
+                                    struct nlattr *data[],
+                                    struct netlink_ext_ack *extack)
 {
        struct nlattr *tb[IFLA_MAX + 1];
-       struct net *net;
        int err;
 
        if (!data || !data[ops->peer_type])
-               return 0;
+               return NULL;
 
        err = rtnl_nla_parse_ifinfomsg(tb, data[ops->peer_type], extack);
        if (err < 0)
-               return err;
+               return ERR_PTR(err);
 
        if (ops->validate) {
                err = ops->validate(tb, NULL, extack);
                if (err < 0)
-                       return err;
+                       return ERR_PTR(err);
        }
 
-       net = rtnl_link_get_net_ifla(tb);
-       if (IS_ERR(net))
-               return PTR_ERR(net);
-       if (net)
-               rtnl_nets_add(rtnl_nets, net);
-
-       return 0;
+       return rtnl_link_get_net_ifla(tb);
 }
 
 static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
                          const struct rtnl_link_ops *ops,
                          struct net *tgt_net, struct net *link_net,
+                         struct net *peer_net,
                          struct rtnl_newlink_tbs *tbs,
                          struct nlattr **data,
                          struct netlink_ext_ack *extack)
                return -EOPNOTSUPP;
        }
 
-       return rtnl_newlink_create(skb, ifm, ops, tgt_net, link_net, nlh, tb, data, extack);
+       return rtnl_newlink_create(skb, ifm, ops, tgt_net, link_net, peer_net, nlh,
+                                  tb, data, extack);
 }
 
 static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
                        struct netlink_ext_ack *extack)
 {
+       struct net *tgt_net, *link_net = NULL, *peer_net = NULL;
        struct nlattr **tb, **linkinfo, **data = NULL;
-       struct net *tgt_net, *link_net = NULL;
        struct rtnl_link_ops *ops = NULL;
        struct rtnl_newlink_tbs *tbs;
        struct rtnl_nets rtnl_nets;
                }
 
                if (ops->peer_type) {
-                       ret = rtnl_add_peer_net(&rtnl_nets, ops, data, extack);
-                       if (ret < 0)
+                       peer_net = rtnl_get_peer_net(ops, data, extack);
+                       if (IS_ERR(peer_net))
                                goto put_ops;
+                       if (peer_net)
+                               rtnl_nets_add(&rtnl_nets, peer_net);
                }
        }
 
        }
 
        rtnl_nets_lock(&rtnl_nets);
-       ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, tbs, data, extack);
+       ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, peer_net, tbs, data, extack);
        rtnl_nets_unlock(&rtnl_nets);
 
 put_net: