@@ -1955,7 +1955,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
IFF_SLAVE_INACTIVE | IFF_BONDING |
- IFF_SLAVE_NEEDARP);
+ IFF_SLAVE_NEEDARP | IFF_SLAVE_FILTER_TX);
kfree(slave);
@@ -2081,7 +2081,7 @@ static int bond_release_all(struct net_device *bond_dev)
}
slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
- IFF_SLAVE_INACTIVE);
+ IFF_SLAVE_INACTIVE | IFF_SLAVE_FILTER_TX);
kfree(slave);
@@ -291,12 +291,15 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave)
slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
if (slave_do_arp_validate(bond, slave))
slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
+ if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+ slave->dev->priv_flags |= IFF_SLAVE_FILTER_TX;
}
static inline void bond_set_slave_active_flags(struct slave *slave)
{
slave->state = BOND_STATE_ACTIVE;
- slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
+ slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP |
+ IFF_SLAVE_FILTER_TX);
}
static inline void bond_set_master_3ad_flags(struct bonding *bond)
@@ -70,6 +70,7 @@
#define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to
* release skb->dst
*/
+#define IFF_SLAVE_FILTER_TX 0x800 /* filter tx on bonding slaves */
#define IF_GET_IFACE 0x0001 /* for querying only */
#define IF_GET_PROTO 0x0002
@@ -1786,6 +1786,25 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
return netdev_get_tx_queue(dev, queue_index);
}
+/* In active-backup mode, on bonding slaves other than the currently active slave,
+ * suppress outgoing packets, except for special L2 protocols.
+ */
+static inline int skb_bond_should_drop_tx(struct sk_buff *skb)
+{
+ struct packet_type *ptype;
+ __be16 type;
+
+ /* allow protocols specifically bound to this interface */
+ type = skb->protocol;
+ list_for_each_entry_rcu(ptype,
+ &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
+ if (ptype->type == type && ptype->dev == skb->dev)
+ return 0;
+ }
+
+ return 1;
+}
+
/**
* dev_queue_xmit - transmit a buffer
* @skb: buffer to transmit
@@ -1818,6 +1837,12 @@ int dev_queue_xmit(struct sk_buff *skb)
struct Qdisc *q;
int rc = -ENOMEM;
+ if ((dev->priv_flags & IFF_SLAVE_FILTER_TX) &&
+ skb_bond_should_drop_tx(skb)) {
+ rc = NET_XMIT_DROP;
+ goto out_kfree_skb;
+ }
+
/* GSO will handle the following emulations directly. */
if (netif_needs_gso(dev, skb))
goto gso;