static bool
may_send_learning_packets(const struct bond *bond)
{
- return !bond->lacp_negotiated && bond->balance != BM_AB;
+ return !bond->lacp_negotiated && bond->balance != BM_AB &&
+ bond->active_slave;
}
/* Returns true if 'bond' needs the client to send out packets to assist with
* MAC learning on 'bond'. If this function returns true, then the client
* should iterate through its MAC learning table for the bridge on which 'bond'
* is located. For each MAC that has been learned on a port other than 'bond',
- * it should call bond_send_learning_packet().
+ * it should call bond_compose_learning_packet().
*
* This function will only return true if 'bond' is in SLB mode and LACP is not
* negotiated. Otherwise sending learning packets isn't necessary.
/* Sends a gratuitous learning packet on 'bond' from 'eth_src' on 'vlan'.
*
- * See bond_should_send_learning_packets() for description of usage. */
-int
-bond_send_learning_packet(struct bond *bond,
- const uint8_t eth_src[ETH_ADDR_LEN],
- uint16_t vlan)
+ * See bond_should_send_learning_packets() for description of usage. The
+ * caller should send the composed packet on the port associated with
+ * port_aux and takes ownership of the returned ofpbuf. */
+struct ofpbuf *
+bond_compose_learning_packet(struct bond *bond,
+ const uint8_t eth_src[ETH_ADDR_LEN],
+ uint16_t vlan, void **port_aux)
{
struct bond_slave *slave;
- struct ofpbuf packet;
+ struct ofpbuf *packet;
struct flow flow;
- int error;
assert(may_send_learning_packets(bond));
- if (!bond->active_slave) {
- /* Nowhere to send the learning packet. */
- return 0;
- }
memset(&flow, 0, sizeof flow);
memcpy(flow.dl_src, eth_src, ETH_ADDR_LEN);
slave = choose_output_slave(bond, &flow, vlan);
- ofpbuf_init(&packet, 0);
- compose_benign_packet(&packet, "Open vSwitch Bond Failover", 0xf177,
+ packet = ofpbuf_new(0);
+ compose_benign_packet(packet, "Open vSwitch Bond Failover", 0xf177,
eth_src);
if (vlan) {
- eth_push_vlan(&packet, htons(vlan));
+ eth_push_vlan(packet, htons(vlan));
}
- error = netdev_send(slave->netdev, &packet);
- ofpbuf_uninit(&packet);
- return error;
+ *port_aux = slave->aux;
+ return packet;
}
\f
/* Checks whether a packet that arrived on 'slave_' within 'bond', with an
}
}
- /* Drop all packets which arrive on backup slaves. This is similar to how
- * Linux bonding handles active-backup bonds. */
- if (bond->balance == BM_AB) {
+ switch (bond->balance) {
+ case BM_AB:
+ /* Drop all packets which arrive on backup slaves. This is similar to
+ * how Linux bonding handles active-backup bonds. */
*tags |= bond_get_active_slave_tag(bond);
if (bond->active_slave != slave) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
slave->name, ETH_ADDR_ARGS(eth_dst));
return BV_DROP;
}
+ return BV_ACCEPT;
+
+ case BM_TCP:
+ /* TCP balancing has degraded to SLB (otherwise the
+ * bond->lacp_negotiated check above would have processed this).
+ *
+ * Fall through. */
+ case BM_SLB:
+ /* Drop all packets for which we have learned a different input port,
+ * because we probably sent the packet on one slave and got it back on
+ * the other. Gratuitous ARP packets are an exception to this rule:
+ * the host has moved to another switch. The exception to the
+ * exception is if we locked the learning table to avoid reflections on
+ * bond slaves. */
+ return BV_DROP_IF_MOVED;
+
+ case BM_STABLE:
+ return BV_ACCEPT;
}
- /* Drop all packets for which we have learned a different input port,
- * because we probably sent the packet on one slave and got it back on the
- * other. Gratuitous ARP packets are an exception to this rule: the host
- * has moved to another switch. The exception to the exception is if we
- * locked the learning table to avoid reflections on bond slaves. */
- return BV_DROP_IF_MOVED;
+ NOT_REACHED();
}
/* Returns the slave (registered on 'bond' by bond_slave_register()) to which
ds_put_format(&ds, "\thash %d: %"PRIu64" kB load\n",
hash, be->tx_bytes / 1024);
- if (bond->balance != BM_SLB) {
- continue;
- }
-
- /* XXX How can we list the MACs assigned to hashes? */
+ /* XXX How can we list the MACs assigned to hashes of SLB bonds? */
}
}
unixctl_command_reply(conn, 200, ds_cstr(&ds));