Skip to content

Commit

Permalink
Merge branch 'netdev_iflink_remove'
Browse files Browse the repository at this point in the history
Nicolas Dichtel says:

====================
Remove iflink field from the net_device structure

The first goal of this series was to advertise the veth peer via the IFLA_LINK
attribute, but iflink was not ready for network namespaces.

The iflink of an interface should be set to its ifindex for a physical interface
and to another value (0 if not relevant) for a virtual interface.
This was not the case for some interfaces, like vxlan, bond, or bridge for
example.
There is also a risk, if the targeted interface moves to another netns, that the
ifindex changes without updating corresponding iflink fields (eg. vlan).

Moving the management of this property into virtual interface drivers allows to
better handle this last case because most of virtual interface drivers have a
pointer to the link netdevice.
Anyway, dev->iflink value was always a copy of some internal data of the virtual
interface driver, thus let's use these internal data directly.

So, this series removes the iflink field and let the drivers manage it.
Only the last patch was present in the v1, but I fully rework it.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 2, 2015
2 parents 033f46b + a45253b commit e4a924f
Show file tree
Hide file tree
Showing 28 changed files with 140 additions and 54 deletions.
8 changes: 8 additions & 0 deletions drivers/infiniband/ulp/ipoib/ipoib_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,13 @@ static void ipoib_set_mcast_list(struct net_device *dev)
queue_work(ipoib_workqueue, &priv->restart_task);
}

static int ipoib_get_iflink(const struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);

return priv->parent->ifindex;
}

static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr)
{
/*
Expand Down Expand Up @@ -1341,6 +1348,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
.ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout,
.ndo_set_rx_mode = ipoib_set_mcast_list,
.ndo_get_iflink = ipoib_get_iflink,
};

void ipoib_setup(struct net_device *dev)
Expand Down
1 change: 0 additions & 1 deletion drivers/infiniband/ulp/ipoib/ipoib_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
}

priv->child_type = type;
priv->dev->iflink = ppriv->dev->ifindex;
list_add_tail(&priv->list, &ppriv->child_intfs);

return 0;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ipvlan/ipvlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
struct rtable *rt;
int err, ret = NET_XMIT_DROP;
struct flowi4 fl4 = {
.flowi4_oif = dev->iflink,
.flowi4_oif = dev_get_iflink(dev),
.flowi4_tos = RT_TOS(ip4h->tos),
.flowi4_flags = FLOWI_FLAG_ANYSRC,
.daddr = ip4h->daddr,
Expand Down
9 changes: 8 additions & 1 deletion drivers/net/ipvlan/ipvlan_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ static int ipvlan_init(struct net_device *dev)
dev->features = phy_dev->features & IPVLAN_FEATURES;
dev->features |= NETIF_F_LLTX;
dev->gso_max_size = phy_dev->gso_max_size;
dev->iflink = phy_dev->ifindex;
dev->hard_header_len = phy_dev->hard_header_len;

ipvlan_set_lockdep_class(dev);
Expand Down Expand Up @@ -305,6 +304,13 @@ static int ipvlan_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
return 0;
}

static int ipvlan_get_iflink(const struct net_device *dev)
{
struct ipvl_dev *ipvlan = netdev_priv(dev);

return ipvlan->phy_dev->ifindex;
}

static const struct net_device_ops ipvlan_netdev_ops = {
.ndo_init = ipvlan_init,
.ndo_uninit = ipvlan_uninit,
Expand All @@ -317,6 +323,7 @@ static const struct net_device_ops ipvlan_netdev_ops = {
.ndo_get_stats64 = ipvlan_get_stats64,
.ndo_vlan_rx_add_vid = ipvlan_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ipvlan_vlan_rx_kill_vid,
.ndo_get_iflink = ipvlan_get_iflink,
};

static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
Expand Down
9 changes: 8 additions & 1 deletion drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,6 @@ static int macvlan_init(struct net_device *dev)
dev->hw_features |= NETIF_F_LRO;
dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES;
dev->gso_max_size = lowerdev->gso_max_size;
dev->iflink = lowerdev->ifindex;
dev->hard_header_len = lowerdev->hard_header_len;

macvlan_set_lockdep_class(dev);
Expand Down Expand Up @@ -995,6 +994,13 @@ static void macvlan_dev_netpoll_cleanup(struct net_device *dev)
}
#endif /* CONFIG_NET_POLL_CONTROLLER */

static int macvlan_dev_get_iflink(const struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);

return vlan->lowerdev->ifindex;
}

static const struct ethtool_ops macvlan_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_settings = macvlan_ethtool_get_settings,
Expand Down Expand Up @@ -1025,6 +1031,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_netpoll_setup = macvlan_dev_netpoll_setup,
.ndo_netpoll_cleanup = macvlan_dev_netpoll_cleanup,
#endif
.ndo_get_iflink = macvlan_dev_get_iflink,
};

void macvlan_common_setup(struct net_device *dev)
Expand Down
15 changes: 15 additions & 0 deletions drivers/net/veth.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,20 @@ static void veth_poll_controller(struct net_device *dev)
}
#endif /* CONFIG_NET_POLL_CONTROLLER */

static int veth_get_iflink(const struct net_device *dev)
{
struct veth_priv *priv = netdev_priv(dev);
struct net_device *peer;
int iflink;

rcu_read_lock();
peer = rcu_dereference(priv->peer);
iflink = peer ? peer->ifindex : 0;
rcu_read_unlock();

return iflink;
}

static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init,
.ndo_open = veth_open,
Expand All @@ -275,6 +289,7 @@ static const struct net_device_ops veth_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = veth_poll_controller,
#endif
.ndo_get_iflink = veth_get_iflink,
};

#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
Expand Down
7 changes: 5 additions & 2 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
* int queue_index, u32 maxrate);
* Called when a user wants to set a max-rate limitation of specific
* TX queue.
* int (*ndo_get_iflink)(const struct net_device *dev);
* Called to get the iflink value of this device.
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
Expand Down Expand Up @@ -1191,6 +1193,7 @@ struct net_device_ops {
int (*ndo_set_tx_maxrate)(struct net_device *dev,
int queue_index,
u32 maxrate);
int (*ndo_get_iflink)(const struct net_device *dev);
};

/**
Expand Down Expand Up @@ -1535,7 +1538,7 @@ struct net_device {
netdev_features_t mpls_features;

int ifindex;
int iflink;
int group;

struct net_device_stats stats;

Expand Down Expand Up @@ -1738,7 +1741,6 @@ struct net_device {
#endif
struct phy_device *phydev;
struct lock_class_key *qdisc_tx_busylock;
int group;
struct pm_qos_request pm_qos_req;
};
#define to_net_dev(d) container_of(d, struct net_device, dev)
Expand Down Expand Up @@ -2149,6 +2151,7 @@ void __dev_remove_pack(struct packet_type *pt);
void dev_add_offload(struct packet_offload *po);
void dev_remove_offload(struct packet_offload *po);

int dev_get_iflink(const struct net_device *dev);
struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
unsigned short mask);
struct net_device *dev_get_by_name(struct net *net, const char *name);
Expand Down
1 change: 1 addition & 0 deletions include/net/ip6_tunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw);
__u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr);
struct net *ip6_tnl_get_link_net(const struct net_device *dev);
int ip6_tnl_get_iflink(const struct net_device *dev);

static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{
Expand Down
1 change: 1 addition & 0 deletions include/net/ip_tunnels.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ int ip_tunnel_init(struct net_device *dev);
void ip_tunnel_uninit(struct net_device *dev);
void ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
struct net *ip_tunnel_get_link_net(const struct net_device *dev);
int ip_tunnel_get_iflink(const struct net_device *dev);
int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname);

Expand Down
9 changes: 8 additions & 1 deletion net/8021q/vlan_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,6 @@ static int vlan_dev_init(struct net_device *dev)
/* IFF_BROADCAST|IFF_MULTICAST; ??? */
dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
IFF_MASTER | IFF_SLAVE);
dev->iflink = real_dev->ifindex;
dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
(1<<__LINK_STATE_DORMANT))) |
(1<<__LINK_STATE_PRESENT);
Expand Down Expand Up @@ -733,6 +732,13 @@ static void vlan_dev_netpoll_cleanup(struct net_device *dev)
}
#endif /* CONFIG_NET_POLL_CONTROLLER */

static int vlan_dev_get_iflink(const struct net_device *dev)
{
struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;

return real_dev->ifindex;
}

static const struct ethtool_ops vlan_ethtool_ops = {
.get_settings = vlan_ethtool_get_settings,
.get_drvinfo = vlan_ethtool_get_drvinfo,
Expand Down Expand Up @@ -769,6 +775,7 @@ static const struct net_device_ops vlan_netdev_ops = {
#endif
.ndo_fix_features = vlan_dev_fix_features,
.ndo_get_lock_subclass = vlan_dev_get_lock_subclass,
.ndo_get_iflink = vlan_dev_get_iflink,
};

static void vlan_dev_free(struct net_device *dev)
Expand Down
5 changes: 3 additions & 2 deletions net/batman-adv/hard-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,12 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
return true;

/* no more parents..stop recursion */
if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex)
if (dev_get_iflink(net_dev) == 0 ||
dev_get_iflink(net_dev) == net_dev->ifindex)
return false;

/* recurse over the parent device */
parent_dev = __dev_get_by_index(&init_net, net_dev->iflink);
parent_dev = __dev_get_by_index(&init_net, dev_get_iflink(net_dev));
/* if we got a NULL parent_dev there is something broken.. */
if (WARN(!parent_dev, "Cannot find parent device"))
return false;
Expand Down
4 changes: 2 additions & 2 deletions net/bridge/br_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,
nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
(dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
(dev->ifindex != dev->iflink &&
nla_put_u32(skb, IFLA_LINK, dev->iflink)))
(dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
goto nla_put_failure;

if (event == RTM_NEWLINK && port) {
Expand Down
32 changes: 22 additions & 10 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,27 @@ __setup("netdev=", netdev_boot_setup);
*******************************************************************************/

/**
* dev_get_iflink - get 'iflink' value of a interface
* @dev: targeted interface
*
* Indicates the ifindex the interface is linked to.
* Physical interfaces have the same 'ifindex' and 'iflink' values.
*/

int dev_get_iflink(const struct net_device *dev)
{
if (dev->netdev_ops && dev->netdev_ops->ndo_get_iflink)
return dev->netdev_ops->ndo_get_iflink(dev);

/* If dev->rtnl_link_ops is set, it's a virtual interface. */
if (dev->rtnl_link_ops)
return 0;

return dev->ifindex;
}
EXPORT_SYMBOL(dev_get_iflink);

/**
* __dev_get_by_name - find a device by its name
* @net: the applicable net namespace
Expand Down Expand Up @@ -6314,8 +6335,6 @@ int register_netdevice(struct net_device *dev)
spin_lock_init(&dev->addr_list_lock);
netdev_set_addr_lockdep_class(dev);

dev->iflink = -1;

ret = dev_get_valid_name(net, dev, dev->name);
if (ret < 0)
goto out;
Expand Down Expand Up @@ -6345,9 +6364,6 @@ int register_netdevice(struct net_device *dev)
else if (__dev_get_by_index(net, dev->ifindex))
goto err_uninit;

if (dev->iflink == -1)
dev->iflink = dev->ifindex;

/* Transfer changeable features to wanted_features and enable
* software offloads (GSO and GRO).
*/
Expand Down Expand Up @@ -7060,12 +7076,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
dev_net_set(dev, net);

/* If there is an ifindex conflict assign a new one */
if (__dev_get_by_index(net, dev->ifindex)) {
int iflink = (dev->iflink == dev->ifindex);
if (__dev_get_by_index(net, dev->ifindex))
dev->ifindex = dev_new_index(net);
if (iflink)
dev->iflink = dev->ifindex;
}

/* Send a netdev-add uevent to the new namespace */
kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
Expand Down
4 changes: 2 additions & 2 deletions net/core/link_watch.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(lweventlist_lock);
static unsigned char default_operstate(const struct net_device *dev)
{
if (!netif_carrier_ok(dev))
return (dev->ifindex != dev->iflink ?
return (dev->ifindex != dev_get_iflink(dev) ?
IF_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);

if (netif_dormant(dev))
Expand Down Expand Up @@ -89,7 +89,7 @@ static bool linkwatch_urgent_event(struct net_device *dev)
if (!netif_running(dev))
return false;

if (dev->ifindex != dev->iflink)
if (dev->ifindex != dev_get_iflink(dev))
return true;

if (dev->priv_flags & IFF_TEAM_PORT)
Expand Down
10 changes: 9 additions & 1 deletion net/core/net-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,19 @@ NETDEVICE_SHOW_RO(dev_id, fmt_hex);
NETDEVICE_SHOW_RO(dev_port, fmt_dec);
NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
NETDEVICE_SHOW_RO(addr_len, fmt_dec);
NETDEVICE_SHOW_RO(iflink, fmt_dec);
NETDEVICE_SHOW_RO(ifindex, fmt_dec);
NETDEVICE_SHOW_RO(type, fmt_dec);
NETDEVICE_SHOW_RO(link_mode, fmt_dec);

static ssize_t iflink_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct net_device *ndev = to_net_dev(dev);

return sprintf(buf, fmt_dec, dev_get_iflink(ndev));
}
static DEVICE_ATTR_RO(iflink);

static ssize_t format_name_assign_type(const struct net_device *dev, char *buf)
{
return sprintf(buf, fmt_dec, dev->name_assign_type);
Expand Down
8 changes: 4 additions & 4 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1055,8 +1055,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
#ifdef CONFIG_RPS
nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
#endif
(dev->ifindex != dev->iflink &&
nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
(dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
(upper_dev &&
nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
Expand Down Expand Up @@ -2863,8 +2863,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
(dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
(dev->ifindex != dev->iflink &&
nla_put_u32(skb, IFLA_LINK, dev->iflink)))
(dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
goto nla_put_failure;

br_afspec = nla_nest_start(skb, IFLA_AF_SPEC);
Expand Down
8 changes: 3 additions & 5 deletions net/dsa/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,11 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)


/* slave device handling ****************************************************/
static int dsa_slave_init(struct net_device *dev)
static int dsa_slave_get_iflink(const struct net_device *dev)
{
struct dsa_slave_priv *p = netdev_priv(dev);

dev->iflink = p->parent->dst->master_netdev->ifindex;

return 0;
return p->parent->dst->master_netdev->ifindex;
}

static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p)
Expand Down Expand Up @@ -664,7 +662,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
};

static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_init = dsa_slave_init,
.ndo_open = dsa_slave_open,
.ndo_stop = dsa_slave_close,
.ndo_start_xmit = dsa_slave_xmit,
Expand All @@ -675,6 +672,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_fdb_del = dsa_slave_fdb_del,
.ndo_fdb_dump = dsa_slave_fdb_dump,
.ndo_do_ioctl = dsa_slave_ioctl,
.ndo_get_iflink = dsa_slave_get_iflink,
};

static const struct swdev_ops dsa_slave_swdev_ops = {
Expand Down
Loading

0 comments on commit e4a924f

Please sign in to comment.