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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ec5d165555
@ -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,
|
|||||||
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) {
|
err = rocker_port_bridge_join(rocker_port, master);
|
||||||
if (!strcmp(master->rtnl_link_ops->kind, "bridge"))
|
else if (netif_is_ovs_master(master))
|
||||||
err = rocker_port_bridge_join(rocker_port, master);
|
err = rocker_port_ovs_changed(rocker_port, master);
|
||||||
else if (!strcmp(master->rtnl_link_ops->kind, "openvswitch"))
|
return err;
|
||||||
err = rocker_port_ovs_changed(rocker_port, master);
|
}
|
||||||
} else if (rocker_port_is_bridged(rocker_port)) {
|
|
||||||
err = rocker_port_bridge_leave(rocker_port);
|
|
||||||
} else if (rocker_port_is_ovsed(rocker_port)) {
|
|
||||||
err = rocker_port_ovs_changed(rocker_port, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
else if (rocker_port_is_ovsed(rocker_port))
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!rocker_port_dev_check(dev))
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case NETDEV_CHANGEUPPER:
|
case NETDEV_CHANGEUPPER:
|
||||||
dev = netdev_notifier_info_to_dev(ptr);
|
info = ptr;
|
||||||
if (!rocker_port_dev_check(dev))
|
if (!info->master)
|
||||||
return NOTIFY_DONE;
|
goto out;
|
||||||
err = rocker_port_master_changed(dev);
|
rocker_port = netdev_priv(dev);
|
||||||
if (err)
|
if (info->linking) {
|
||||||
netdev_warn(dev,
|
err = rocker_port_master_linked(rocker_port,
|
||||||
"failed to reflect master change (err %d)\n",
|
info->upper_dev);
|
||||||
err);
|
if (err)
|
||||||
|
netdev_warn(dev, "failed to reflect master linked (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);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
|||||||
* @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 {
|
|||||||
#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 {
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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);
|
|||||||
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,
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user