/* Legacy compatibility. */
long long int next_fake_iface_update; /* LLONG_MAX if disabled. */
+ bool lacp_fallback_ab; /* Fallback to active-backup on LACP failure. */
atomic_int ref_cnt;
};
bond->updelay = s->up_delay;
bond->downdelay = s->down_delay;
+ if (bond->lacp_fallback_ab != s->lacp_fallback_ab_cfg) {
+ bond->lacp_fallback_ab = s->lacp_fallback_ab_cfg;
+ revalidate = true;
+ }
+
if (bond->rebalance_interval != s->rebalance_interval) {
bond->rebalance_interval = s->rebalance_interval;
revalidate = true;
static bool
may_send_learning_packets(const struct bond *bond)
{
- return bond->lacp_status == LACP_DISABLED
- && (bond->balance == BM_SLB || bond->balance == BM_AB)
+ return ((bond->lacp_status == LACP_DISABLED
+ && (bond->balance == BM_SLB || bond->balance == BM_AB))
+ || (bond->lacp_fallback_ab && bond->lacp_status == LACP_CONFIGURED))
&& bond->active_slave;
}
* packets to them.
*
* If LACP is configured, but LACP negotiations have been unsuccessful, we
- * drop all incoming traffic. */
+ * drop all incoming traffic except if lacp_fallback_ab is enabled. */
switch (bond->lacp_status) {
case LACP_NEGOTIATED:
verdict = slave->enabled ? BV_ACCEPT : BV_DROP;
goto out;
case LACP_CONFIGURED:
- goto out;
+ if (!bond->lacp_fallback_ab) {
+ goto out;
+ }
case LACP_DISABLED:
break;
}
}
switch (bond->balance) {
+ case BM_TCP:
+ /* TCP balanced bonds require successful LACP negotiations. Based on the
+ * above check, LACP is off or lacp_fallback_ab is true on this bond.
+ * If lacp_fallback_ab is true fall through to BM_AB case else, we
+ * drop all incoming traffic. */
+ if (!bond->lacp_fallback_ab) {
+ goto out;
+ }
+
case BM_AB:
/* Drop all packets which arrive on backup slaves. This is similar to
* how Linux bonding handles active-backup bonds. */
verdict = BV_ACCEPT;
goto out;
- case BM_TCP:
- /* TCP balanced bonds require successful LACP negotiated. Based on the
- * above check, LACP is off on this bond. Therfore, we drop all
- * incoming traffic. */
- goto out;
-
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
to->tx_bytes += delta;
/* Arrange for flows to be revalidated. */
+ hash->slave = to;
bond->bond_revalidate = true;
}
uint32_t basis;
if (vlan_s) {
- if (sscanf(vlan_s, "%u", &vlan) != 1) {
+ if (!ovs_scan(vlan_s, "%u", &vlan)) {
unixctl_command_reply_error(conn, "invalid vlan");
return;
}
}
if (basis_s) {
- if (sscanf(basis_s, "%"PRIu32, &basis) != 1) {
+ if (!ovs_scan(basis_s, "%"SCNu32, &basis)) {
unixctl_command_reply_error(conn, "invalid basis");
return;
}
basis = 0;
}
- if (sscanf(mac_s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))
- == ETH_ADDR_SCAN_COUNT) {
+ if (ovs_scan(mac_s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
hash = bond_hash_src(mac, vlan, basis) & BOND_MASK;
hash_cstr = xasprintf("%u", hash);
struct flow_wildcards *wc, uint16_t vlan)
{
struct bond_entry *e;
+ int balance;
+ balance = bond->balance;
if (bond->lacp_status == LACP_CONFIGURED) {
/* LACP has been configured on this bond but negotiations were
- * unsuccussful. Drop all traffic. */
- return NULL;
+ * unsuccussful. If lacp_fallback_ab is enabled use active-
+ * backup mode else drop all traffic. */
+ if (!bond->lacp_fallback_ab) {
+ return NULL;
+ }
+ balance = BM_AB;
}
- switch (bond->balance) {
+ switch (balance) {
case BM_AB:
return bond->active_slave;