Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+42 −32
Original line number Diff line number Diff line
@@ -322,21 +322,16 @@ static u16 rocker_port_vlan_to_vid(const struct rocker_port *rocker_port,
	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)
{
	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)
{
	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)
@@ -5331,46 +5326,61 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port,
	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;

	/* N.B: Do nothing if the type of master is not supported */
	if (master && master->rtnl_link_ops) {
		if (!strcmp(master->rtnl_link_ops->kind, "bridge"))
	if (netif_is_bridge_master(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);
	} 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);
	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);
	else if (rocker_port_is_ovsed(rocker_port))
		err = rocker_port_ovs_changed(rocker_port, NULL);
	return err;
}

static int rocker_netdevice_event(struct notifier_block *unused,
				  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;

	switch (event) {
	case NETDEV_CHANGEUPPER:
		dev = netdev_notifier_info_to_dev(ptr);
	if (!rocker_port_dev_check(dev))
		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)
			netdev_warn(dev,
				    "failed to reflect master change (err %d)\n",
				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;
	}

out:
	return NOTIFY_DONE;
}

+40 −35
Original line number Diff line number Diff line
@@ -1240,13 +1240,8 @@ struct net_device_ops {
 *
 * @IFF_802_1Q_VLAN: 802.1Q VLAN 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_SLAVE_NEEDARP: need ARPs for validation
 * @IFF_ISATAP: ISATAP interface (RFC4214)
 * @IFF_MASTER_ARPMON: bonding master, ARP mon in use
 * @IFF_WAN_HDLC: WAN HDLC device
 * @IFF_XMIT_DST_RELEASE: dev_hard_start_xmit() is allowed to
 *	release skb->dst
@@ -1264,46 +1259,38 @@ struct net_device_ops {
 * @IFF_MACVLAN: Macvlan device
 * @IFF_VRF_MASTER: device is a VRF master
 * @IFF_NO_QUEUE: device can run without qdisc attached
 * @IFF_OPENVSWITCH: device is a Open vSwitch master
 */
enum netdev_priv_flags {
	IFF_802_1Q_VLAN			= 1<<0,
	IFF_EBRIDGE			= 1<<1,
	IFF_SLAVE_INACTIVE		= 1<<2,
	IFF_MASTER_8023AD		= 1<<3,
	IFF_MASTER_ALB			= 1<<4,
	IFF_BONDING			= 1<<5,
	IFF_SLAVE_NEEDARP		= 1<<6,
	IFF_ISATAP			= 1<<7,
	IFF_MASTER_ARPMON		= 1<<8,
	IFF_WAN_HDLC			= 1<<9,
	IFF_XMIT_DST_RELEASE		= 1<<10,
	IFF_DONT_BRIDGE			= 1<<11,
	IFF_DISABLE_NETPOLL		= 1<<12,
	IFF_MACVLAN_PORT		= 1<<13,
	IFF_BRIDGE_PORT			= 1<<14,
	IFF_OVS_DATAPATH		= 1<<15,
	IFF_TX_SKB_SHARING		= 1<<16,
	IFF_UNICAST_FLT			= 1<<17,
	IFF_TEAM_PORT			= 1<<18,
	IFF_SUPP_NOFCS			= 1<<19,
	IFF_LIVE_ADDR_CHANGE		= 1<<20,
	IFF_MACVLAN			= 1<<21,
	IFF_XMIT_DST_RELEASE_PERM	= 1<<22,
	IFF_IPVLAN_MASTER		= 1<<23,
	IFF_IPVLAN_SLAVE		= 1<<24,
	IFF_VRF_MASTER			= 1<<25,
	IFF_NO_QUEUE			= 1<<26,
	IFF_BONDING			= 1<<2,
	IFF_ISATAP			= 1<<3,
	IFF_WAN_HDLC			= 1<<4,
	IFF_XMIT_DST_RELEASE		= 1<<5,
	IFF_DONT_BRIDGE			= 1<<6,
	IFF_DISABLE_NETPOLL		= 1<<7,
	IFF_MACVLAN_PORT		= 1<<8,
	IFF_BRIDGE_PORT			= 1<<9,
	IFF_OVS_DATAPATH		= 1<<10,
	IFF_TX_SKB_SHARING		= 1<<11,
	IFF_UNICAST_FLT			= 1<<12,
	IFF_TEAM_PORT			= 1<<13,
	IFF_SUPP_NOFCS			= 1<<14,
	IFF_LIVE_ADDR_CHANGE		= 1<<15,
	IFF_MACVLAN			= 1<<16,
	IFF_XMIT_DST_RELEASE_PERM	= 1<<17,
	IFF_IPVLAN_MASTER		= 1<<18,
	IFF_IPVLAN_SLAVE		= 1<<19,
	IFF_VRF_MASTER			= 1<<20,
	IFF_NO_QUEUE			= 1<<21,
	IFF_OPENVSWITCH			= 1<<22,
};

#define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
#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_SLAVE_NEEDARP		IFF_SLAVE_NEEDARP
#define IFF_ISATAP			IFF_ISATAP
#define IFF_MASTER_ARPMON		IFF_MASTER_ARPMON
#define IFF_WAN_HDLC			IFF_WAN_HDLC
#define IFF_XMIT_DST_RELEASE		IFF_XMIT_DST_RELEASE
#define IFF_DONT_BRIDGE			IFF_DONT_BRIDGE
@@ -1322,6 +1309,7 @@ enum netdev_priv_flags {
#define IFF_IPVLAN_SLAVE		IFF_IPVLAN_SLAVE
#define IFF_VRF_MASTER			IFF_VRF_MASTER
#define IFF_NO_QUEUE			IFF_NO_QUEUE
#define IFF_OPENVSWITCH			IFF_OPENVSWITCH

/**
 *	struct net_device - The DEVICE structure.
@@ -2127,6 +2115,13 @@ struct netdev_notifier_change_info {
	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,
					     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;
}

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)
{
	bool rc = false;
+14 −2
Original line number Diff line number Diff line
@@ -5311,6 +5311,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
				   struct net_device *upper_dev, bool master,
				   void *private)
{
	struct netdev_notifier_changeupper_info changeupper_info;
	struct netdev_adjacent *i, *j, *to_i, *to_j;
	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))
		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,
						   master);
	if (ret)
@@ -5367,7 +5372,8 @@ static int __netdev_upper_dev_link(struct net_device *dev,
			goto rollback_lower_mesh;
	}

	call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev);
	call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
				      &changeupper_info.info);
	return 0;

rollback_lower_mesh:
@@ -5462,9 +5468,14 @@ EXPORT_SYMBOL(netdev_master_upper_dev_link_private);
void netdev_upper_dev_unlink(struct net_device *dev,
			     struct net_device *upper_dev)
{
	struct netdev_notifier_changeupper_info changeupper_info;
	struct netdev_adjacent *i, *j;
	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);

	/* 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)
		__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);

+1 −1
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ static void do_setup(struct net_device *netdev)
	netdev->netdev_ops = &internal_dev_netdev_ops;

	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->ethtool_ops = &internal_dev_ethtool_ops;
	netdev->rtnl_link_ops = &internal_dev_link_ops;