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

Merge branch 'rocker-master-change'

Jiri Pirko says:

====================
rocker: make master change handling nicer

Jiri Pirko (6):
  net: introduce change upper device notifier change info
  net: add netif_is_bridge_master helper
  net: add netif_is_ovs_master helper with IFF_OPENVSWITCH private flag
  net: kill long time unused bonding private flags
  rocker: use new helper to figure out master kind
  rocker: use change upper info
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 547c890c 686ed304
...@@ -322,21 +322,16 @@ static u16 rocker_port_vlan_to_vid(const struct rocker_port *rocker_port, ...@@ -322,21 +322,16 @@ static u16 rocker_port_vlan_to_vid(const struct rocker_port *rocker_port,
return ntohs(vlan_id); return ntohs(vlan_id);
} }
static bool rocker_port_is_slave(const struct rocker_port *rocker_port,
const char *kind)
{
return rocker_port->bridge_dev &&
!strcmp(rocker_port->bridge_dev->rtnl_link_ops->kind, kind);
}
static bool rocker_port_is_bridged(const struct rocker_port *rocker_port) static bool rocker_port_is_bridged(const struct rocker_port *rocker_port)
{ {
return rocker_port_is_slave(rocker_port, "bridge"); return rocker_port->bridge_dev &&
netif_is_bridge_master(rocker_port->bridge_dev);
} }
static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port) static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port)
{ {
return rocker_port_is_slave(rocker_port, "openvswitch"); return rocker_port->bridge_dev &&
netif_is_ovs_master(rocker_port->bridge_dev);
} }
#define ROCKER_OP_FLAG_REMOVE BIT(0) #define ROCKER_OP_FLAG_REMOVE BIT(0)
...@@ -5331,46 +5326,61 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port, ...@@ -5331,46 +5326,61 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port,
return err; return err;
} }
static int rocker_port_master_changed(struct net_device *dev) static int rocker_port_master_linked(struct rocker_port *rocker_port,
struct net_device *master)
{ {
struct rocker_port *rocker_port = netdev_priv(dev);
struct net_device *master = netdev_master_upper_dev_get(dev);
int err = 0; int err = 0;
/* N.B: Do nothing if the type of master is not supported */ if (netif_is_bridge_master(master))
if (master && master->rtnl_link_ops) {
if (!strcmp(master->rtnl_link_ops->kind, "bridge"))
err = rocker_port_bridge_join(rocker_port, master); err = rocker_port_bridge_join(rocker_port, master);
else if (!strcmp(master->rtnl_link_ops->kind, "openvswitch")) else if (netif_is_ovs_master(master))
err = rocker_port_ovs_changed(rocker_port, master); err = rocker_port_ovs_changed(rocker_port, master);
} else if (rocker_port_is_bridged(rocker_port)) { return err;
}
static int rocker_port_master_unlinked(struct rocker_port *rocker_port)
{
int err = 0;
if (rocker_port_is_bridged(rocker_port))
err = rocker_port_bridge_leave(rocker_port); err = rocker_port_bridge_leave(rocker_port);
} else if (rocker_port_is_ovsed(rocker_port)) { else if (rocker_port_is_ovsed(rocker_port))
err = rocker_port_ovs_changed(rocker_port, NULL); err = rocker_port_ovs_changed(rocker_port, NULL);
}
return err; return err;
} }
static int rocker_netdevice_event(struct notifier_block *unused, static int rocker_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct net_device *dev; struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct netdev_notifier_changeupper_info *info;
struct rocker_port *rocker_port;
int err; int err;
switch (event) {
case NETDEV_CHANGEUPPER:
dev = netdev_notifier_info_to_dev(ptr);
if (!rocker_port_dev_check(dev)) if (!rocker_port_dev_check(dev))
return NOTIFY_DONE; return NOTIFY_DONE;
err = rocker_port_master_changed(dev);
switch (event) {
case NETDEV_CHANGEUPPER:
info = ptr;
if (!info->master)
goto out;
rocker_port = netdev_priv(dev);
if (info->linking) {
err = rocker_port_master_linked(rocker_port,
info->upper_dev);
if (err) if (err)
netdev_warn(dev, netdev_warn(dev, "failed to reflect master linked (err %d)\n",
"failed to reflect master change (err %d)\n", err);
} else {
err = rocker_port_master_unlinked(rocker_port);
if (err)
netdev_warn(dev, "failed to reflect master unlinked (err %d)\n",
err); err);
}
break; break;
} }
out:
return NOTIFY_DONE; return NOTIFY_DONE;
} }
......
...@@ -1240,13 +1240,8 @@ struct net_device_ops { ...@@ -1240,13 +1240,8 @@ struct net_device_ops {
* *
* @IFF_802_1Q_VLAN: 802.1Q VLAN device * @IFF_802_1Q_VLAN: 802.1Q VLAN device
* @IFF_EBRIDGE: Ethernet bridging device * @IFF_EBRIDGE: Ethernet bridging device
* @IFF_SLAVE_INACTIVE: bonding slave not the curr. active
* @IFF_MASTER_8023AD: bonding master, 802.3ad
* @IFF_MASTER_ALB: bonding master, balance-alb
* @IFF_BONDING: bonding master or slave * @IFF_BONDING: bonding master or slave
* @IFF_SLAVE_NEEDARP: need ARPs for validation
* @IFF_ISATAP: ISATAP interface (RFC4214) * @IFF_ISATAP: ISATAP interface (RFC4214)
* @IFF_MASTER_ARPMON: bonding master, ARP mon in use
* @IFF_WAN_HDLC: WAN HDLC device * @IFF_WAN_HDLC: WAN HDLC device
* @IFF_XMIT_DST_RELEASE: dev_hard_start_xmit() is allowed to * @IFF_XMIT_DST_RELEASE: dev_hard_start_xmit() is allowed to
* release skb->dst * release skb->dst
...@@ -1264,46 +1259,38 @@ struct net_device_ops { ...@@ -1264,46 +1259,38 @@ struct net_device_ops {
* @IFF_MACVLAN: Macvlan device * @IFF_MACVLAN: Macvlan device
* @IFF_VRF_MASTER: device is a VRF master * @IFF_VRF_MASTER: device is a VRF master
* @IFF_NO_QUEUE: device can run without qdisc attached * @IFF_NO_QUEUE: device can run without qdisc attached
* @IFF_OPENVSWITCH: device is a Open vSwitch master
*/ */
enum netdev_priv_flags { enum netdev_priv_flags {
IFF_802_1Q_VLAN = 1<<0, IFF_802_1Q_VLAN = 1<<0,
IFF_EBRIDGE = 1<<1, IFF_EBRIDGE = 1<<1,
IFF_SLAVE_INACTIVE = 1<<2, IFF_BONDING = 1<<2,
IFF_MASTER_8023AD = 1<<3, IFF_ISATAP = 1<<3,
IFF_MASTER_ALB = 1<<4, IFF_WAN_HDLC = 1<<4,
IFF_BONDING = 1<<5, IFF_XMIT_DST_RELEASE = 1<<5,
IFF_SLAVE_NEEDARP = 1<<6, IFF_DONT_BRIDGE = 1<<6,
IFF_ISATAP = 1<<7, IFF_DISABLE_NETPOLL = 1<<7,
IFF_MASTER_ARPMON = 1<<8, IFF_MACVLAN_PORT = 1<<8,
IFF_WAN_HDLC = 1<<9, IFF_BRIDGE_PORT = 1<<9,
IFF_XMIT_DST_RELEASE = 1<<10, IFF_OVS_DATAPATH = 1<<10,
IFF_DONT_BRIDGE = 1<<11, IFF_TX_SKB_SHARING = 1<<11,
IFF_DISABLE_NETPOLL = 1<<12, IFF_UNICAST_FLT = 1<<12,
IFF_MACVLAN_PORT = 1<<13, IFF_TEAM_PORT = 1<<13,
IFF_BRIDGE_PORT = 1<<14, IFF_SUPP_NOFCS = 1<<14,
IFF_OVS_DATAPATH = 1<<15, IFF_LIVE_ADDR_CHANGE = 1<<15,
IFF_TX_SKB_SHARING = 1<<16, IFF_MACVLAN = 1<<16,
IFF_UNICAST_FLT = 1<<17, IFF_XMIT_DST_RELEASE_PERM = 1<<17,
IFF_TEAM_PORT = 1<<18, IFF_IPVLAN_MASTER = 1<<18,
IFF_SUPP_NOFCS = 1<<19, IFF_IPVLAN_SLAVE = 1<<19,
IFF_LIVE_ADDR_CHANGE = 1<<20, IFF_VRF_MASTER = 1<<20,
IFF_MACVLAN = 1<<21, IFF_NO_QUEUE = 1<<21,
IFF_XMIT_DST_RELEASE_PERM = 1<<22, IFF_OPENVSWITCH = 1<<22,
IFF_IPVLAN_MASTER = 1<<23,
IFF_IPVLAN_SLAVE = 1<<24,
IFF_VRF_MASTER = 1<<25,
IFF_NO_QUEUE = 1<<26,
}; };
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN #define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
#define IFF_EBRIDGE IFF_EBRIDGE #define IFF_EBRIDGE IFF_EBRIDGE
#define IFF_SLAVE_INACTIVE IFF_SLAVE_INACTIVE
#define IFF_MASTER_8023AD IFF_MASTER_8023AD
#define IFF_MASTER_ALB IFF_MASTER_ALB
#define IFF_BONDING IFF_BONDING #define IFF_BONDING IFF_BONDING
#define IFF_SLAVE_NEEDARP IFF_SLAVE_NEEDARP
#define IFF_ISATAP IFF_ISATAP #define IFF_ISATAP IFF_ISATAP
#define IFF_MASTER_ARPMON IFF_MASTER_ARPMON
#define IFF_WAN_HDLC IFF_WAN_HDLC #define IFF_WAN_HDLC IFF_WAN_HDLC
#define IFF_XMIT_DST_RELEASE IFF_XMIT_DST_RELEASE #define IFF_XMIT_DST_RELEASE IFF_XMIT_DST_RELEASE
#define IFF_DONT_BRIDGE IFF_DONT_BRIDGE #define IFF_DONT_BRIDGE IFF_DONT_BRIDGE
...@@ -1322,6 +1309,7 @@ enum netdev_priv_flags { ...@@ -1322,6 +1309,7 @@ enum netdev_priv_flags {
#define IFF_IPVLAN_SLAVE IFF_IPVLAN_SLAVE #define IFF_IPVLAN_SLAVE IFF_IPVLAN_SLAVE
#define IFF_VRF_MASTER IFF_VRF_MASTER #define IFF_VRF_MASTER IFF_VRF_MASTER
#define IFF_NO_QUEUE IFF_NO_QUEUE #define IFF_NO_QUEUE IFF_NO_QUEUE
#define IFF_OPENVSWITCH IFF_OPENVSWITCH
/** /**
* struct net_device - The DEVICE structure. * struct net_device - The DEVICE structure.
...@@ -2127,6 +2115,13 @@ struct netdev_notifier_change_info { ...@@ -2127,6 +2115,13 @@ struct netdev_notifier_change_info {
unsigned int flags_changed; unsigned int flags_changed;
}; };
struct netdev_notifier_changeupper_info {
struct netdev_notifier_info info; /* must be first */
struct net_device *upper_dev; /* new upper dev */
bool master; /* is upper dev master */
bool linking; /* is the nofication for link or unlink */
};
static inline void netdev_notifier_info_init(struct netdev_notifier_info *info, static inline void netdev_notifier_info_init(struct netdev_notifier_info *info,
struct net_device *dev) struct net_device *dev)
{ {
...@@ -3841,6 +3836,16 @@ static inline bool netif_is_vrf(const struct net_device *dev) ...@@ -3841,6 +3836,16 @@ static inline bool netif_is_vrf(const struct net_device *dev)
return dev->priv_flags & IFF_VRF_MASTER; return dev->priv_flags & IFF_VRF_MASTER;
} }
static inline bool netif_is_bridge_master(const struct net_device *dev)
{
return dev->priv_flags & IFF_EBRIDGE;
}
static inline bool netif_is_ovs_master(const struct net_device *dev)
{
return dev->priv_flags & IFF_OPENVSWITCH;
}
static inline bool netif_index_is_vrf(struct net *net, int ifindex) static inline bool netif_index_is_vrf(struct net *net, int ifindex)
{ {
bool rc = false; bool rc = false;
......
...@@ -5311,6 +5311,7 @@ static int __netdev_upper_dev_link(struct net_device *dev, ...@@ -5311,6 +5311,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev, bool master, struct net_device *upper_dev, bool master,
void *private) void *private)
{ {
struct netdev_notifier_changeupper_info changeupper_info;
struct netdev_adjacent *i, *j, *to_i, *to_j; struct netdev_adjacent *i, *j, *to_i, *to_j;
int ret = 0; int ret = 0;
...@@ -5329,6 +5330,10 @@ static int __netdev_upper_dev_link(struct net_device *dev, ...@@ -5329,6 +5330,10 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (master && netdev_master_upper_dev_get(dev)) if (master && netdev_master_upper_dev_get(dev))
return -EBUSY; return -EBUSY;
changeupper_info.upper_dev = upper_dev;
changeupper_info.master = master;
changeupper_info.linking = true;
ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private, ret = __netdev_adjacent_dev_link_neighbour(dev, upper_dev, private,
master); master);
if (ret) if (ret)
...@@ -5367,7 +5372,8 @@ static int __netdev_upper_dev_link(struct net_device *dev, ...@@ -5367,7 +5372,8 @@ static int __netdev_upper_dev_link(struct net_device *dev,
goto rollback_lower_mesh; goto rollback_lower_mesh;
} }
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
&changeupper_info.info);
return 0; return 0;
rollback_lower_mesh: rollback_lower_mesh:
...@@ -5462,9 +5468,14 @@ EXPORT_SYMBOL(netdev_master_upper_dev_link_private); ...@@ -5462,9 +5468,14 @@ EXPORT_SYMBOL(netdev_master_upper_dev_link_private);
void netdev_upper_dev_unlink(struct net_device *dev, void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev) struct net_device *upper_dev)
{ {
struct netdev_notifier_changeupper_info changeupper_info;
struct netdev_adjacent *i, *j; struct netdev_adjacent *i, *j;
ASSERT_RTNL(); ASSERT_RTNL();
changeupper_info.upper_dev = upper_dev;
changeupper_info.master = netdev_master_upper_dev_get(dev) == upper_dev;
changeupper_info.linking = false;
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
/* Here is the tricky part. We must remove all dev's lower /* Here is the tricky part. We must remove all dev's lower
...@@ -5484,7 +5495,8 @@ void netdev_upper_dev_unlink(struct net_device *dev, ...@@ -5484,7 +5495,8 @@ void netdev_upper_dev_unlink(struct net_device *dev,
list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
__netdev_adjacent_dev_unlink(dev, i->dev); __netdev_adjacent_dev_unlink(dev, i->dev);
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev); call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
&changeupper_info.info);
} }
EXPORT_SYMBOL(netdev_upper_dev_unlink); EXPORT_SYMBOL(netdev_upper_dev_unlink);
......
...@@ -135,7 +135,7 @@ static void do_setup(struct net_device *netdev) ...@@ -135,7 +135,7 @@ static void do_setup(struct net_device *netdev)
netdev->netdev_ops = &internal_dev_netdev_ops; netdev->netdev_ops = &internal_dev_netdev_ops;
netdev->priv_flags &= ~IFF_TX_SKB_SHARING; netdev->priv_flags &= ~IFF_TX_SKB_SHARING;
netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_OPENVSWITCH;
netdev->destructor = internal_dev_destructor; netdev->destructor = internal_dev_destructor;
netdev->ethtool_ops = &internal_dev_ethtool_ops; netdev->ethtool_ops = &internal_dev_ethtool_ops;
netdev->rtnl_link_ops = &internal_dev_link_ops; netdev->rtnl_link_ops = &internal_dev_link_ops;
......
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