Commit e4a924f5 authored by David S. Miller's avatar David S. Miller

Merge branch 'netdev_iflink_remove'

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 033f46b3 a45253bf
...@@ -842,6 +842,13 @@ static void ipoib_set_mcast_list(struct net_device *dev) ...@@ -842,6 +842,13 @@ static void ipoib_set_mcast_list(struct net_device *dev)
queue_work(ipoib_workqueue, &priv->restart_task); 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) static u32 ipoib_addr_hash(struct ipoib_neigh_hash *htbl, u8 *daddr)
{ {
/* /*
...@@ -1341,6 +1348,7 @@ static const struct net_device_ops ipoib_netdev_ops = { ...@@ -1341,6 +1348,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
.ndo_start_xmit = ipoib_start_xmit, .ndo_start_xmit = ipoib_start_xmit,
.ndo_tx_timeout = ipoib_timeout, .ndo_tx_timeout = ipoib_timeout,
.ndo_set_rx_mode = ipoib_set_mcast_list, .ndo_set_rx_mode = ipoib_set_mcast_list,
.ndo_get_iflink = ipoib_get_iflink,
}; };
void ipoib_setup(struct net_device *dev) void ipoib_setup(struct net_device *dev)
......
...@@ -102,7 +102,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv, ...@@ -102,7 +102,6 @@ int __ipoib_vlan_add(struct ipoib_dev_priv *ppriv, struct ipoib_dev_priv *priv,
} }
priv->child_type = type; priv->child_type = type;
priv->dev->iflink = ppriv->dev->ifindex;
list_add_tail(&priv->list, &ppriv->child_intfs); list_add_tail(&priv->list, &ppriv->child_intfs);
return 0; return 0;
......
...@@ -330,7 +330,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb) ...@@ -330,7 +330,7 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
struct rtable *rt; struct rtable *rt;
int err, ret = NET_XMIT_DROP; int err, ret = NET_XMIT_DROP;
struct flowi4 fl4 = { struct flowi4 fl4 = {
.flowi4_oif = dev->iflink, .flowi4_oif = dev_get_iflink(dev),
.flowi4_tos = RT_TOS(ip4h->tos), .flowi4_tos = RT_TOS(ip4h->tos),
.flowi4_flags = FLOWI_FLAG_ANYSRC, .flowi4_flags = FLOWI_FLAG_ANYSRC,
.daddr = ip4h->daddr, .daddr = ip4h->daddr,
......
...@@ -114,7 +114,6 @@ static int ipvlan_init(struct net_device *dev) ...@@ -114,7 +114,6 @@ static int ipvlan_init(struct net_device *dev)
dev->features = phy_dev->features & IPVLAN_FEATURES; dev->features = phy_dev->features & IPVLAN_FEATURES;
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
dev->gso_max_size = phy_dev->gso_max_size; dev->gso_max_size = phy_dev->gso_max_size;
dev->iflink = phy_dev->ifindex;
dev->hard_header_len = phy_dev->hard_header_len; dev->hard_header_len = phy_dev->hard_header_len;
ipvlan_set_lockdep_class(dev); ipvlan_set_lockdep_class(dev);
...@@ -305,6 +304,13 @@ static int ipvlan_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, ...@@ -305,6 +304,13 @@ static int ipvlan_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
return 0; 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 = { static const struct net_device_ops ipvlan_netdev_ops = {
.ndo_init = ipvlan_init, .ndo_init = ipvlan_init,
.ndo_uninit = ipvlan_uninit, .ndo_uninit = ipvlan_uninit,
...@@ -317,6 +323,7 @@ static const struct net_device_ops ipvlan_netdev_ops = { ...@@ -317,6 +323,7 @@ static const struct net_device_ops ipvlan_netdev_ops = {
.ndo_get_stats64 = ipvlan_get_stats64, .ndo_get_stats64 = ipvlan_get_stats64,
.ndo_vlan_rx_add_vid = ipvlan_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = ipvlan_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ipvlan_vlan_rx_kill_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, static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
......
...@@ -786,7 +786,6 @@ static int macvlan_init(struct net_device *dev) ...@@ -786,7 +786,6 @@ static int macvlan_init(struct net_device *dev)
dev->hw_features |= NETIF_F_LRO; dev->hw_features |= NETIF_F_LRO;
dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES; dev->vlan_features = lowerdev->vlan_features & MACVLAN_FEATURES;
dev->gso_max_size = lowerdev->gso_max_size; dev->gso_max_size = lowerdev->gso_max_size;
dev->iflink = lowerdev->ifindex;
dev->hard_header_len = lowerdev->hard_header_len; dev->hard_header_len = lowerdev->hard_header_len;
macvlan_set_lockdep_class(dev); macvlan_set_lockdep_class(dev);
...@@ -995,6 +994,13 @@ static void macvlan_dev_netpoll_cleanup(struct net_device *dev) ...@@ -995,6 +994,13 @@ static void macvlan_dev_netpoll_cleanup(struct net_device *dev)
} }
#endif /* CONFIG_NET_POLL_CONTROLLER */ #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 = { static const struct ethtool_ops macvlan_ethtool_ops = {
.get_link = ethtool_op_get_link, .get_link = ethtool_op_get_link,
.get_settings = macvlan_ethtool_get_settings, .get_settings = macvlan_ethtool_get_settings,
...@@ -1025,6 +1031,7 @@ static const struct net_device_ops macvlan_netdev_ops = { ...@@ -1025,6 +1031,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_netpoll_setup = macvlan_dev_netpoll_setup, .ndo_netpoll_setup = macvlan_dev_netpoll_setup,
.ndo_netpoll_cleanup = macvlan_dev_netpoll_cleanup, .ndo_netpoll_cleanup = macvlan_dev_netpoll_cleanup,
#endif #endif
.ndo_get_iflink = macvlan_dev_get_iflink,
}; };
void macvlan_common_setup(struct net_device *dev) void macvlan_common_setup(struct net_device *dev)
......
...@@ -263,6 +263,20 @@ static void veth_poll_controller(struct net_device *dev) ...@@ -263,6 +263,20 @@ static void veth_poll_controller(struct net_device *dev)
} }
#endif /* CONFIG_NET_POLL_CONTROLLER */ #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 = { static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init, .ndo_init = veth_dev_init,
.ndo_open = veth_open, .ndo_open = veth_open,
...@@ -275,6 +289,7 @@ static const struct net_device_ops veth_netdev_ops = { ...@@ -275,6 +289,7 @@ static const struct net_device_ops veth_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = veth_poll_controller, .ndo_poll_controller = veth_poll_controller,
#endif #endif
.ndo_get_iflink = veth_get_iflink,
}; };
#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \ #define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
......
...@@ -1030,6 +1030,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev, ...@@ -1030,6 +1030,8 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
* int queue_index, u32 maxrate); * int queue_index, u32 maxrate);
* Called when a user wants to set a max-rate limitation of specific * Called when a user wants to set a max-rate limitation of specific
* TX queue. * TX queue.
* int (*ndo_get_iflink)(const struct net_device *dev);
* Called to get the iflink value of this device.
*/ */
struct net_device_ops { struct net_device_ops {
int (*ndo_init)(struct net_device *dev); int (*ndo_init)(struct net_device *dev);
...@@ -1191,6 +1193,7 @@ struct net_device_ops { ...@@ -1191,6 +1193,7 @@ struct net_device_ops {
int (*ndo_set_tx_maxrate)(struct net_device *dev, int (*ndo_set_tx_maxrate)(struct net_device *dev,
int queue_index, int queue_index,
u32 maxrate); u32 maxrate);
int (*ndo_get_iflink)(const struct net_device *dev);
}; };
/** /**
...@@ -1535,7 +1538,7 @@ struct net_device { ...@@ -1535,7 +1538,7 @@ struct net_device {
netdev_features_t mpls_features; netdev_features_t mpls_features;
int ifindex; int ifindex;
int iflink; int group;
struct net_device_stats stats; struct net_device_stats stats;
...@@ -1738,7 +1741,6 @@ struct net_device { ...@@ -1738,7 +1741,6 @@ struct net_device {
#endif #endif
struct phy_device *phydev; struct phy_device *phydev;
struct lock_class_key *qdisc_tx_busylock; struct lock_class_key *qdisc_tx_busylock;
int group;
struct pm_qos_request pm_qos_req; struct pm_qos_request pm_qos_req;
}; };
#define to_net_dev(d) container_of(d, struct net_device, dev) #define to_net_dev(d) container_of(d, struct net_device, dev)
...@@ -2149,6 +2151,7 @@ void __dev_remove_pack(struct packet_type *pt); ...@@ -2149,6 +2151,7 @@ void __dev_remove_pack(struct packet_type *pt);
void dev_add_offload(struct packet_offload *po); void dev_add_offload(struct packet_offload *po);
void dev_remove_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, struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
unsigned short mask); unsigned short mask);
struct net_device *dev_get_by_name(struct net *net, const char *name); struct net_device *dev_get_by_name(struct net *net, const char *name);
......
...@@ -71,6 +71,7 @@ __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw); ...@@ -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, __u32 ip6_tnl_get_cap(struct ip6_tnl *t, const struct in6_addr *laddr,
const struct in6_addr *raddr); const struct in6_addr *raddr);
struct net *ip6_tnl_get_link_net(const struct net_device *dev); 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) static inline void ip6tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
......
...@@ -142,6 +142,7 @@ int ip_tunnel_init(struct net_device *dev); ...@@ -142,6 +142,7 @@ int ip_tunnel_init(struct net_device *dev);
void ip_tunnel_uninit(struct net_device *dev); void ip_tunnel_uninit(struct net_device *dev);
void ip_tunnel_dellink(struct net_device *dev, struct list_head *head); void ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
struct net *ip_tunnel_get_link_net(const struct net_device *dev); 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, int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname); struct rtnl_link_ops *ops, char *devname);
......
...@@ -538,7 +538,6 @@ static int vlan_dev_init(struct net_device *dev) ...@@ -538,7 +538,6 @@ static int vlan_dev_init(struct net_device *dev)
/* IFF_BROADCAST|IFF_MULTICAST; ??? */ /* IFF_BROADCAST|IFF_MULTICAST; ??? */
dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | dev->flags = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
IFF_MASTER | IFF_SLAVE); IFF_MASTER | IFF_SLAVE);
dev->iflink = real_dev->ifindex;
dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
(1<<__LINK_STATE_DORMANT))) | (1<<__LINK_STATE_DORMANT))) |
(1<<__LINK_STATE_PRESENT); (1<<__LINK_STATE_PRESENT);
...@@ -733,6 +732,13 @@ static void vlan_dev_netpoll_cleanup(struct net_device *dev) ...@@ -733,6 +732,13 @@ static void vlan_dev_netpoll_cleanup(struct net_device *dev)
} }
#endif /* CONFIG_NET_POLL_CONTROLLER */ #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 = { static const struct ethtool_ops vlan_ethtool_ops = {
.get_settings = vlan_ethtool_get_settings, .get_settings = vlan_ethtool_get_settings,
.get_drvinfo = vlan_ethtool_get_drvinfo, .get_drvinfo = vlan_ethtool_get_drvinfo,
...@@ -769,6 +775,7 @@ static const struct net_device_ops vlan_netdev_ops = { ...@@ -769,6 +775,7 @@ static const struct net_device_ops vlan_netdev_ops = {
#endif #endif
.ndo_fix_features = vlan_dev_fix_features, .ndo_fix_features = vlan_dev_fix_features,
.ndo_get_lock_subclass = vlan_dev_get_lock_subclass, .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) static void vlan_dev_free(struct net_device *dev)
......
...@@ -83,11 +83,12 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) ...@@ -83,11 +83,12 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
return true; return true;
/* no more parents..stop recursion */ /* 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; return false;
/* recurse over the parent device */ /* 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 we got a NULL parent_dev there is something broken.. */
if (WARN(!parent_dev, "Cannot find parent device")) if (WARN(!parent_dev, "Cannot find parent device"))
return false; return false;
......
...@@ -305,8 +305,8 @@ static int br_fill_ifinfo(struct sk_buff *skb, ...@@ -305,8 +305,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,
nla_put_u8(skb, IFLA_OPERSTATE, operstate) || nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
(dev->addr_len && (dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
(dev->ifindex != dev->iflink && (dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev->iflink))) nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
goto nla_put_failure; goto nla_put_failure;
if (event == RTM_NEWLINK && port) { if (event == RTM_NEWLINK && port) {
......
...@@ -659,6 +659,27 @@ __setup("netdev=", netdev_boot_setup); ...@@ -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 * __dev_get_by_name - find a device by its name
* @net: the applicable net namespace * @net: the applicable net namespace
...@@ -6314,8 +6335,6 @@ int register_netdevice(struct net_device *dev) ...@@ -6314,8 +6335,6 @@ int register_netdevice(struct net_device *dev)
spin_lock_init(&dev->addr_list_lock); spin_lock_init(&dev->addr_list_lock);
netdev_set_addr_lockdep_class(dev); netdev_set_addr_lockdep_class(dev);
dev->iflink = -1;
ret = dev_get_valid_name(net, dev, dev->name); ret = dev_get_valid_name(net, dev, dev->name);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -6345,9 +6364,6 @@ int register_netdevice(struct net_device *dev) ...@@ -6345,9 +6364,6 @@ int register_netdevice(struct net_device *dev)
else if (__dev_get_by_index(net, dev->ifindex)) else if (__dev_get_by_index(net, dev->ifindex))
goto err_uninit; goto err_uninit;
if (dev->iflink == -1)
dev->iflink = dev->ifindex;
/* Transfer changeable features to wanted_features and enable /* Transfer changeable features to wanted_features and enable
* software offloads (GSO and GRO). * software offloads (GSO and GRO).
*/ */
...@@ -7060,12 +7076,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char ...@@ -7060,12 +7076,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
dev_net_set(dev, net); dev_net_set(dev, net);
/* If there is an ifindex conflict assign a new one */ /* If there is an ifindex conflict assign a new one */
if (__dev_get_by_index(net, dev->ifindex)) { if (__dev_get_by_index(net, dev->ifindex))
int iflink = (dev->iflink == dev->ifindex);
dev->ifindex = dev_new_index(net); dev->ifindex = dev_new_index(net);
if (iflink)
dev->iflink = dev->ifindex;
}
/* Send a netdev-add uevent to the new namespace */ /* Send a netdev-add uevent to the new namespace */
kobject_uevent(&dev->dev.kobj, KOBJ_ADD); kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
......
...@@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(lweventlist_lock); ...@@ -40,7 +40,7 @@ static DEFINE_SPINLOCK(lweventlist_lock);
static unsigned char default_operstate(const struct net_device *dev) static unsigned char default_operstate(const struct net_device *dev)
{ {
if (!netif_carrier_ok(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_OPER_LOWERLAYERDOWN : IF_OPER_DOWN);
if (netif_dormant(dev)) if (netif_dormant(dev))
...@@ -89,7 +89,7 @@ static bool linkwatch_urgent_event(struct net_device *dev) ...@@ -89,7 +89,7 @@ static bool linkwatch_urgent_event(struct net_device *dev)
if (!netif_running(dev)) if (!netif_running(dev))
return false; return false;
if (dev->ifindex != dev->iflink) if (dev->ifindex != dev_get_iflink(dev))
return true; return true;
if (dev->priv_flags & IFF_TEAM_PORT) if (dev->priv_flags & IFF_TEAM_PORT)
......
...@@ -109,11 +109,19 @@ NETDEVICE_SHOW_RO(dev_id, fmt_hex); ...@@ -109,11 +109,19 @@ NETDEVICE_SHOW_RO(dev_id, fmt_hex);
NETDEVICE_SHOW_RO(dev_port, fmt_dec); NETDEVICE_SHOW_RO(dev_port, fmt_dec);
NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec); NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec);
NETDEVICE_SHOW_RO(addr_len, fmt_dec); NETDEVICE_SHOW_RO(addr_len, fmt_dec);
NETDEVICE_SHOW_RO(iflink, fmt_dec);
NETDEVICE_SHOW_RO(ifindex, fmt_dec); NETDEVICE_SHOW_RO(ifindex, fmt_dec);
NETDEVICE_SHOW_RO(type, fmt_dec); NETDEVICE_SHOW_RO(type, fmt_dec);
NETDEVICE_SHOW_RO(link_mode, 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) static ssize_t format_name_assign_type(const struct net_device *dev, char *buf)
{ {
return sprintf(buf, fmt_dec, dev->name_assign_type); return sprintf(buf, fmt_dec, dev->name_assign_type);
......
...@@ -1055,8 +1055,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, ...@@ -1055,8 +1055,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
#ifdef CONFIG_RPS #ifdef CONFIG_RPS
nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) || nla_put_u32(skb, IFLA_NUM_RX_QUEUES, dev->num_rx_queues) ||
#endif #endif
(dev->ifindex != dev->iflink && (dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev->iflink)) || nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
(upper_dev && (upper_dev &&
nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) || nla_put_u32(skb, IFLA_MASTER, upper_dev->ifindex)) ||
nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) || nla_put_u8(skb, IFLA_CARRIER, netif_carrier_ok(dev)) ||
...@@ -2863,8 +2863,8 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, ...@@ -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)) || nla_put_u32(skb, IFLA_MASTER, br_dev->ifindex)) ||
(dev->addr_len && (dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
(dev->ifindex != dev->iflink && (dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev->iflink))) nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
goto nla_put_failure; goto nla_put_failure;
br_afspec = nla_nest_start(skb, IFLA_AF_SPEC); br_afspec = nla_nest_start(skb, IFLA_AF_SPEC);
......
...@@ -55,13 +55,11 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) ...@@ -55,13 +55,11 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
/* slave device handling ****************************************************/ /* 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); struct dsa_slave_priv *p = netdev_priv(dev);
dev->iflink = p->parent->dst->master_netdev->ifindex; return p->parent->dst->master_netdev->ifindex;
return 0;
} }
static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p) static inline bool dsa_port_is_bridged(struct dsa_slave_priv *p)
...@@ -664,7 +662,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { ...@@ -664,7 +662,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
}; };
static const struct net_device_ops dsa_slave_netdev_ops = { static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_init = dsa_slave_init,
.ndo_open = dsa_slave_open, .ndo_open = dsa_slave_open,
.ndo_stop = dsa_slave_close, .ndo_stop = dsa_slave_close,
.ndo_start_xmit = dsa_slave_xmit, .ndo_start_xmit = dsa_slave_xmit,
...@@ -675,6 +672,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = { ...@@ -675,6 +672,7 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
.ndo_fdb_del = dsa_slave_fdb_del, .ndo_fdb_del = dsa_slave_fdb_del,
.ndo_fdb_dump = dsa_slave_fdb_dump, .ndo_fdb_dump = dsa_slave_fdb_dump,
.ndo_do_ioctl = dsa_slave_ioctl, .ndo_do_ioctl = dsa_slave_ioctl,
.ndo_get_iflink = dsa_slave_get_iflink,
}; };
static const struct swdev_ops dsa_slave_swdev_ops = { static const struct swdev_ops dsa_slave_swdev_ops = {
......
...@@ -456,6 +456,7 @@ static const struct net_device_ops ipgre_netdev_ops = { ...@@ -456,6 +456,7 @@ static const struct net_device_ops ipgre_netdev_ops = {
.ndo_do_ioctl = ipgre_tunnel_ioctl, .ndo_do_ioctl = ipgre_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu, .ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
}; };
#define GRE_FEATURES (NETIF_F_SG | \ #define GRE_FEATURES (NETIF_F_SG | \
...@@ -686,6 +687,7 @@ static const struct net_device_ops gre_tap_netdev_ops = { ...@@ -686,6 +687,7 @@ static const struct net_device_ops gre_tap_netdev_ops = {
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ip_tunnel_change_mtu, .ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
}; };
static void ipgre_tap_setup(struct net_device *dev) static void ipgre_tap_setup(struct net_device *dev)
......
...@@ -389,7 +389,6 @@ static int ip_tunnel_bind_dev(struct net_device *dev) ...@@ -389,7 +389,6 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
hlen = tdev->hard_header_len + tdev->needed_headroom; hlen = tdev->hard_header_len + tdev->needed_headroom;
mtu = tdev->mtu; mtu = tdev->mtu;
} }
dev->iflink = tunnel->parms.link;
dev->needed_headroom = t_hlen + hlen; dev->needed_headroom = t_hlen + hlen;
mtu -= (dev->hard_header_len + t_hlen); mtu -= (dev->hard_header_len + t_hlen);
...@@ -980,6 +979,14 @@ struct net *ip_tunnel_get_link_net(const struct net_device *dev) ...@@ -980,6 +979,14 @@ struct net *ip_tunnel_get_link_net(const struct net_device *dev)
} }
EXPORT_SYMBOL(ip_tunnel_get_link_net); EXPORT_SYMBOL(ip_tunnel_get_link_net);
int ip_tunnel_get_iflink(const struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
return tunnel->parms.link;
}
EXPORT_SYMBOL(ip_tunnel_get_iflink);
int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname) struct rtnl_link_ops *ops, char *devname)
{ {
......
...@@ -341,6 +341,7 @@ static const struct net_device_ops vti_netdev_ops = { ...@@ -341,6 +341,7 @@ static const struct net_device_ops vti_netdev_ops = {
.ndo_do_ioctl = vti_tunnel_ioctl, .ndo_do_ioctl = vti_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu, .ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
}; };
static void vti_tunnel_setup(struct net_device *dev) static void vti_tunnel_setup(struct net_device *dev)
...@@ -361,7 +362,6 @@ static int vti_tunnel_init(struct net_device *dev) ...@@ -361,7 +362,6 @@ static int vti_tunnel_init(struct net_device *dev)
dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr);
dev->mtu = ETH_DATA_LEN; dev->mtu = ETH_DATA_LEN;
dev->flags = IFF_NOARP; dev->flags = IFF_NOARP;
dev->iflink = 0;
dev->addr_len = 4; dev->addr_len = 4;
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
netif_keep_dst(dev); netif_keep_dst(dev);
......
...@@ -272,6 +272,7 @@ static const struct net_device_ops ipip_netdev_ops = { ...@@ -272,6 +272,7 @@ static const struct net_device_ops ipip_netdev_ops = {
.ndo_do_ioctl = ipip_tunnel_ioctl, .ndo_do_ioctl = ipip_tunnel_ioctl,
.ndo_change_mtu = ip_tunnel_change_mtu, .ndo_change_mtu = ip_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
}; };
#define IPIP_FEATURES (NETIF_F_SG | \ #define IPIP_FEATURES (NETIF_F_SG | \
...@@ -286,7 +287,6 @@ static void ipip_tunnel_setup(struct net_device *dev) ...@@ -286,7 +287,6 @@ static void ipip_tunnel_setup(struct net_device *dev)
dev->type = ARPHRD_TUNNEL; dev->type = ARPHRD_TUNNEL;
dev->flags = IFF_NOARP; dev->flags = IFF_NOARP;
dev->iflink = 0;
dev->addr_len = 4; dev->addr_len = 4;
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
netif_keep_dst(dev); netif_keep_dst(dev);
......
...@@ -473,8 +473,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -473,8 +473,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static int reg_vif_get_iflink(const struct net_device *dev)
{
return 0;
}
static const struct net_device_ops reg_vif_netdev_ops = { static const struct net_device_ops reg_vif_netdev_ops = {
.ndo_start_xmit = reg_vif_xmit, .ndo_start_xmit = reg_vif_xmit,
.ndo_get_iflink = reg_vif_get_iflink,
}; };
static void reg_vif_setup(struct net_device *dev) static void reg_vif_setup(struct net_device *dev)
...@@ -509,7 +515,6 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) ...@@ -509,7 +515,6 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt)
free_netdev(dev); free_netdev(dev);
return NULL; return NULL;
} }
dev->iflink = 0;
rcu_read_lock(); rcu_read_lock();
in_dev = __in_dev_get_rcu(dev); in_dev = __in_dev_get_rcu(dev);
...@@ -801,7 +806,7 @@ static int vif_add(struct net *net, struct mr_table *mrt, ...@@ -801,7 +806,7 @@ static int vif_add(struct net *net, struct mr_table *mrt,
v->pkt_out = 0; v->pkt_out = 0;
v->link = dev->ifindex; v->link = dev->ifindex;
if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER)) if (v->flags & (VIFF_TUNNEL | VIFF_REGISTER))
v->link = dev->iflink; v->link = dev_get_iflink(dev);
/* And finish update writing critical data */ /* And finish update writing critical data */
write_lock_bh(&mrt_lock); write_lock_bh(&mrt_lock);
......
...@@ -4858,8 +4858,8 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, ...@@ -4858,8 +4858,8 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
(dev->addr_len && (dev->addr_len &&
nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
nla_put_u32(skb, IFLA_MTU, dev->mtu) || nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
(dev->ifindex != dev->iflink && (dev->ifindex != dev_get_iflink(dev) &&
nla_put_u32(skb, IFLA_LINK, dev->iflink))) nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))))
goto nla_put_failure; goto nla_put_failure;
protoinfo = nla_nest_start(skb, IFLA_PROTINFO); protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
if (!protoinfo) if (!protoinfo)
......
...@@ -1216,6 +1216,7 @@ static const struct net_device_ops ip6gre_netdev_ops = { ...@@ -1216,6 +1216,7 @@ static const struct net_device_ops ip6gre_netdev_ops = {
.ndo_do_ioctl = ip6gre_tunnel_ioctl, .ndo_do_ioctl = ip6gre_tunnel_ioctl,
.ndo_change_mtu = ip6gre_tunnel_change_mtu, .ndo_change_mtu = ip6gre_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip6_tnl_get_iflink,
}; };
static void ip6gre_dev_free(struct net_device *dev) static void ip6gre_dev_free(struct net_device *dev)
...@@ -1238,7 +1239,6 @@ static void ip6gre_tunnel_setup(struct net_device *dev) ...@@ -1238,7 +1239,6 @@ static void ip6gre_tunnel_setup(struct net_device *dev)
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
dev->mtu -= 8; dev->mtu -= 8;
dev->flags |= IFF_NOARP; dev->flags |= IFF_NOARP;
dev->iflink = 0;
dev->addr_len = sizeof(struct in6_addr); dev->addr_len = sizeof(struct in6_addr);
netif_keep_dst(dev); netif_keep_dst(dev);
} }
...@@ -1270,8 +1270,6 @@ static int ip6gre_tunnel_init(struct net_device *dev) ...@@ -1270,8 +1270,6 @@ static int ip6gre_tunnel_init(struct net_device *dev)
u64_stats_init(&ip6gre_tunnel_stats->syncp); u64_stats_init(&ip6gre_tunnel_stats->syncp);
} }
dev->iflink = tunnel->parms.link;
return 0; return 0;
} }
...@@ -1480,8 +1478,6 @@ static int ip6gre_tap_init(struct net_device *dev) ...@@ -1480,8 +1478,6 @@ static int ip6gre_tap_init(struct net_device *dev)
if (!dev->tstats) if (!dev->tstats)
return -ENOMEM; return -ENOMEM;
dev->iflink = tunnel->parms.link;
return 0; return 0;
} }
...@@ -1493,6 +1489,7 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = { ...@@ -1493,6 +1489,7 @@ static const struct net_device_ops ip6gre_tap_netdev_ops = {
.ndo_validate_addr = eth_validate_addr, .ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ip6gre_tunnel_change_mtu, .ndo_change_mtu = ip6gre_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip6_tnl_get_iflink,
}; };
static void ip6gre_tap_setup(struct net_device *dev) static void ip6gre_tap_setup(struct net_device *dev)
...@@ -1503,7 +1500,6 @@ static void ip6gre_tap_setup(struct net_device *dev) ...@@ -1503,7 +1500,6 @@ static void ip6gre_tap_setup(struct net_device *dev)
dev->netdev_ops = &ip6gre_tap_netdev_ops; dev->netdev_ops = &ip6gre_tap_netdev_ops;
dev->destructor = ip6gre_dev_free; dev->destructor = ip6gre_dev_free;
dev->iflink = 0;
dev->features |= NETIF_F_NETNS_LOCAL; dev->features |= NETIF_F_NETNS_LOCAL;
} }
......
...@@ -1264,8 +1264,6 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) ...@@ -1264,8 +1264,6 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
else else
dev->flags &= ~IFF_POINTOPOINT; dev->flags &= ~IFF_POINTOPOINT;
dev->iflink = p->link;
if (p->flags & IP6_TNL_F_CAP_XMIT) { if (p->flags & IP6_TNL_F_CAP_XMIT) {
int strict = (ipv6_addr_type(&p->raddr) & int strict = (ipv6_addr_type(&p->raddr) &
(IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL));
...@@ -1517,6 +1515,13 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) ...@@ -1517,6 +1515,13 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
return 0; return 0;
} }
int ip6_tnl_get_iflink(const struct net_device *dev)
{
struct ip6_tnl *t = netdev_priv(dev);
return t->parms.link;
}
EXPORT_SYMBOL(ip6_tnl_get_iflink);
static const struct net_device_ops ip6_tnl_netdev_ops = { static const struct net_device_ops ip6_tnl_netdev_ops = {
.ndo_init = ip6_tnl_dev_init, .ndo_init = ip6_tnl_dev_init,
...@@ -1525,6 +1530,7 @@ static const struct net_device_ops ip6_tnl_netdev_ops = { ...@@ -1525,6 +1530,7 @@ static const struct net_device_ops ip6_tnl_netdev_ops = {
.ndo_do_ioctl = ip6_tnl_ioctl, .ndo_do_ioctl = ip6_tnl_ioctl,
.ndo_change_mtu = ip6_tnl_change_mtu, .ndo_change_mtu = ip6_tnl_change_mtu,
.ndo_get_stats = ip6_get_stats, .ndo_get_stats = ip6_get_stats,
.ndo_get_iflink = ip6_tnl_get_iflink,
}; };
......
...@@ -601,8 +601,6 @@ static void vti6_link_config(struct ip6_tnl *t) ...@@ -601,8 +601,6 @@ static void vti6_link_config(struct ip6_tnl *t)
dev->flags |= IFF_POINTOPOINT; dev->flags |= IFF_POINTOPOINT;
else else
dev->flags &= ~IFF_POINTOPOINT; dev->flags &= ~IFF_POINTOPOINT;
dev->iflink = p->link;
} }
/** /**
...@@ -808,6 +806,7 @@ static const struct net_device_ops vti6_netdev_ops = { ...@@ -808,6 +806,7 @@ static const struct net_device_ops vti6_netdev_ops = {
.ndo_do_ioctl = vti6_ioctl, .ndo_do_ioctl = vti6_ioctl,
.ndo_change_mtu = vti6_change_mtu, .ndo_change_mtu = vti6_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip6_tnl_get_iflink,
}; };
/** /**
......
...@@ -718,8 +718,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, ...@@ -718,8 +718,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static int reg_vif_get_iflink(const struct net_device *dev)
{
return 0;
}
static const struct net_device_ops reg_vif_netdev_ops = { static const struct net_device_ops reg_vif_netdev_ops = {
.ndo_start_xmit = reg_vif_xmit, .ndo_start_xmit = reg_vif_xmit,
.ndo_get_iflink = reg_vif_get_iflink,
}; };
static void reg_vif_setup(struct net_device *dev) static void reg_vif_setup(struct net_device *dev)
...@@ -752,7 +758,6 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) ...@@ -752,7 +758,6 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt)
free_netdev(dev); free_netdev(dev);
return NULL; return NULL;
} }
dev->iflink = 0;
if (dev_open(dev)) if (dev_open(dev))
goto failure; goto failure;
...@@ -992,7 +997,7 @@ static int mif6_add(struct net *net, struct mr6_table *mrt, ...@@ -992,7 +997,7 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
v->pkt_out = 0; v->pkt_out = 0;
v->link = dev->ifindex; v->link = dev->ifindex;
if (v->flags & MIFF_REGISTER) if (v->flags & MIFF_REGISTER)
v->link = dev->iflink; v->link = dev_get_iflink(dev);
/* And finish update writing critical data */ /* And finish update writing critical data */
write_lock_bh(&mrt_lock); write_lock_bh(&mrt_lock);
......
...@@ -1076,7 +1076,6 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) ...@@ -1076,7 +1076,6 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
if (dev->mtu < IPV6_MIN_MTU) if (dev->mtu < IPV6_MIN_MTU)
dev->mtu = IPV6_MIN_MTU; dev->mtu = IPV6_MIN_MTU;
} }
dev->iflink = tunnel->parms.link;
} }
static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p) static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
...@@ -1336,6 +1335,7 @@ static const struct net_device_ops ipip6_netdev_ops = { ...@@ -1336,6 +1335,7 @@ static const struct net_device_ops ipip6_netdev_ops = {
.ndo_do_ioctl = ipip6_tunnel_ioctl, .ndo_do_ioctl = ipip6_tunnel_ioctl,
.ndo_change_mtu = ipip6_tunnel_change_mtu, .ndo_change_mtu = ipip6_tunnel_change_mtu,
.ndo_get_stats64 = ip_tunnel_get_stats64, .ndo_get_stats64 = ip_tunnel_get_stats64,
.ndo_get_iflink = ip_tunnel_get_iflink,
}; };
static void ipip6_dev_free(struct net_device *dev) static void ipip6_dev_free(struct net_device *dev)
...@@ -1366,7 +1366,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) ...@@ -1366,7 +1366,6 @@ static void ipip6_tunnel_setup(struct net_device *dev)
dev->mtu = ETH_DATA_LEN - t_hlen; dev->mtu = ETH_DATA_LEN - t_hlen;
dev->flags = IFF_NOARP; dev->flags = IFF_NOARP;
netif_keep_dst(dev); netif_keep_dst(dev);
dev->iflink = 0;
dev->addr_len = 4; dev->addr_len = 4;
dev->features |= NETIF_F_LLTX; dev->features |= NETIF_F_LLTX;
dev->features |= SIT_FEATURES; dev->features |= SIT_FEATURES;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment