AT_BANNER([lacp])

# Strips out Reciulation ID information since it may change over time.
m4_define([STRIP_RECIRC_ID], [[sed '
    s/Recirc-ID.*$/<del>/
' ]])

# Strips out active member mac address since it may change over time.
m4_define([STRIP_ACTIVE_MEMBER_MAC], [[sed '
    s/active member mac.*$/<active member mac del>/
' ]])

AT_SETUP([lacp - config])
OVS_VSWITCHD_START([\
        add-port br0 p1 --\
        set Port p1 lacp=active --\
        set Interface p1 type=dummy ])

ovs-appctl time/stop
ovs-appctl time/warp 300 100

AT_CHECK([ovs-appctl lacp/show], [0], [dnl
---- p1 ----
  status: active negotiated
  sys_id: aa:55:aa:55:00:00
  sys_priority: 65535
  aggregation key: 1
  lacp_time: slow

member: p1: expired attached
  port_id: 1
  port_priority: 65535
  may_enable: false

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65535
  actor port_id: 1
  actor port_priority: 65535
  actor key: 1
  actor state: activity synchronized collecting distributing expired

  partner sys_id: 00:00:00:00:00:00
  partner sys_priority: 0
  partner port_id: 0
  partner port_priority: 0
  partner key: 0
  partner state: timeout
])
AT_CHECK([ovs-appctl bond/show])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([lacp - multi port config])
OVS_VSWITCHD_START([dnl
        add-bond br0 bond p1 p2 --\
        set Port bond lacp=active bond-mode=active-backup \
            other_config:lacp-time="fast" \
            other_config:lacp-system-id=11:22:33:44:55:66 \
            other_config:lacp-system-priority=54321 --\
        set Interface p1 type=dummy \
            other_config:lacp-port-id=11 \
            other_config:lacp-port-priority=111 \
            other_config:lacp-aggregation-key=3333 --\
        set Interface p2 type=dummy \
            other_config:lacp-port-id=22 \
            other_config:lacp-port-priority=222 \
            other_config:lacp-aggregation-key=3333 ])

ovs-appctl time/stop
ovs-appctl time/warp 300 100

AT_CHECK([ovs-appctl lacp/show], [0], [stdout])
AT_CHECK([sed -e 's/aggregation key:.*/aggregation key: <omitted>/' < stdout], [0], [dnl
---- bond ----
  status: active negotiated
  sys_id: 11:22:33:44:55:66
  sys_priority: 54321
  aggregation key: <omitted>
  lacp_time: fast

member: p1: expired attached
  port_id: 11
  port_priority: 111
  may_enable: false

  actor sys_id: 11:22:33:44:55:66
  actor sys_priority: 54321
  actor port_id: 11
  actor port_priority: 111
  actor key: 3333
  actor state: activity timeout aggregation synchronized collecting distributing expired

  partner sys_id: 00:00:00:00:00:00
  partner sys_priority: 0
  partner port_id: 0
  partner port_priority: 0
  partner key: 0
  partner state: timeout

member: p2: expired attached
  port_id: 22
  port_priority: 222
  may_enable: false

  actor sys_id: 11:22:33:44:55:66
  actor sys_priority: 54321
  actor port_id: 22
  actor port_priority: 222
  actor key: 3333
  actor state: activity timeout aggregation synchronized collecting distributing expired

  partner sys_id: 00:00:00:00:00:00
  partner sys_priority: 0
  partner port_id: 0
  partner port_priority: 0
  partner key: 0
  partner state: timeout
])
AT_CHECK([ovs-appctl bond/show], [0], [dnl
---- bond ----
bond_mode: active-backup
bond may use recirculation: no, Recirc-ID : -1
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
active member mac: 00:00:00:00:00:00(none)

member p1: disabled
  may_enable: false

member p2: disabled
  may_enable: false

])
OVS_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([lacp - negotiation])
# Create bond0 on br0 with members p0 and p1
#    and bond1 on br1 with members p2 and p3
# with p0 patched to p2 and p1 patched to p3.
OVS_VSWITCHD_START(
  [add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p0 type=patch options:peer=p2 ofport_request=1 \
                    other-config:lacp-aggregation-key=2 -- \
   set interface p1 type=patch options:peer=p3 ofport_request=2 \
                    other-config:lacp-aggregation-key=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p2 p3 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p2 type=patch options:peer=p0 ofport_request=3 \
                    other-config:lacp-aggregation-key=4 -- \
   set interface p3 type=patch options:peer=p1 ofport_request=4 \
                    other-config:lacp-aggregation-key=4 --])

AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])

ovs-appctl time/stop

# Wait for up to 5 (simulated) seconds, until LACP negotiation finishes.
i=0
while :; do
    ovs-appctl lacp/show bond0 > bond0
    AT_CAPTURE_FILE([bond0])
    ovs-appctl lacp/show bond1 > bond1
    AT_CAPTURE_FILE([bond1])
    if grep negotiated bond0 && grep negotiated bond1; then
        if grep expired bond0 || grep expired bond1; then
            :
        else
            break
        fi
    fi
    i=`expr $i + 1`
    if test $i = 50; then
        AT_FAIL_IF([:])
    fi
    ovs-appctl time/warp 100
done

# Now check the correctly negotiated configuration.
AT_CHECK(
  [ovs-appctl lacp/show bond0
ovs-appctl lacp/show bond1
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [stdout])
AT_CHECK([sed '/active member/d' stdout], [0], [dnl
---- bond0 ----
  status: active negotiated
  sys_id: aa:55:aa:55:00:00
  sys_priority: 65534
  aggregation key: 2
  lacp_time: fast

member: p0: current attached
  port_id: 1
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 1
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 3
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation synchronized collecting distributing

member: p1: current attached
  port_id: 2
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 2
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 4
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond1 ----
  status: active negotiated
  sys_id: aa:66:aa:66:00:00
  sys_priority: 65534
  aggregation key: 4
  lacp_time: fast

member: p2: current attached
  port_id: 3
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 3
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 1
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation synchronized collecting distributing

member: p3: current attached
  port_id: 4
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 4
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 2
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond0 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>

member p0: enabled
  may_enable: true

member p1: enabled
  may_enable: true

---- bond1 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>

member p2: enabled
  may_enable: true

member p3: enabled
  may_enable: true

])
AT_CHECK([grep 'active member$' stdout], [0], [dnl
  active member
  active member
])

# Redirect the patch link between p0 and p2 so that no packets get
# back and forth across them anymore.  Then wait 4 simulated
# seconds.  The LACP state should become "expired" for p0 and p2.
AT_CHECK([ovs-vsctl \
-- add-port br0 null0 -- set int null0 type=patch options:peer=p2 -- set int p2 options:peer=null0 \
-- add-port br1 null1 -- set int null1 type=patch options:peer=p0 -- set int p0 options:peer=null1])

ovs-appctl time/warp 4100 100
AT_CHECK(
  [ovs-appctl lacp/show bond0
ovs-appctl lacp/show bond1
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [dnl
---- bond0 ----
  status: active negotiated
  sys_id: aa:55:aa:55:00:00
  sys_priority: 65534
  aggregation key: 2
  lacp_time: fast

member: p0: expired attached
  port_id: 1
  port_priority: 65535
  may_enable: false

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 1
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing expired

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 3
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation collecting distributing

member: p1: current attached
  port_id: 2
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 2
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 4
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond1 ----
  status: active negotiated
  sys_id: aa:66:aa:66:00:00
  sys_priority: 65534
  aggregation key: 4
  lacp_time: fast

member: p2: expired attached
  port_id: 3
  port_priority: 65535
  may_enable: false

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 3
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing expired

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 1
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation collecting distributing

member: p3: current attached
  port_id: 4
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 4
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 2
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond0 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p0: disabled
  may_enable: false

member p1: enabled
  active member
  may_enable: true

---- bond1 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p2: disabled
  may_enable: false

member p3: enabled
  active member
  may_enable: true

])

# Wait 4 more simulated seconds.  The LACP state should become
# "defaulted" for p0 and p2.
ovs-appctl time/warp 4100 100
AT_CHECK(
  [ovs-appctl lacp/show bond0
ovs-appctl lacp/show bond1
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [dnl
---- bond0 ----
  status: active negotiated
  sys_id: aa:55:aa:55:00:00
  sys_priority: 65534
  aggregation key: 2
  lacp_time: fast

member: p0: defaulted detached
  port_id: 1
  port_priority: 65535
  may_enable: false

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 1
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation defaulted

  partner sys_id: 00:00:00:00:00:00
  partner sys_priority: 0
  partner port_id: 0
  partner port_priority: 0
  partner key: 0
  partner state:

member: p1: current attached
  port_id: 2
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 2
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 4
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond1 ----
  status: active negotiated
  sys_id: aa:66:aa:66:00:00
  sys_priority: 65534
  aggregation key: 4
  lacp_time: fast

member: p2: defaulted detached
  port_id: 3
  port_priority: 65535
  may_enable: false

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 3
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation defaulted

  partner sys_id: 00:00:00:00:00:00
  partner sys_priority: 0
  partner port_id: 0
  partner port_priority: 0
  partner key: 0
  partner state:

member: p3: current attached
  port_id: 4
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 4
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 2
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond0 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p0: disabled
  may_enable: false

member p1: enabled
  active member
  may_enable: true

---- bond1 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p2: disabled
  may_enable: false

member p3: enabled
  active member
  may_enable: true

])

# Reconnect the patch link between p0 and p2 to allow traffic between the ports.
AT_CHECK([ovs-vsctl \
-- del-port null0 -- set int p2 options:peer=p0 \
-- del-port null1 -- set int p0 options:peer=p2])

# Wait for 30 more seconds (LACP_SLOW_TIME_TX) for the lacp to renegotiate
ovs-appctl time/warp 30100 100

AT_CHECK(
  [ovs-appctl lacp/show bond0
ovs-appctl lacp/show bond1
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [dnl
---- bond0 ----
  status: active negotiated
  sys_id: aa:55:aa:55:00:00
  sys_priority: 65534
  aggregation key: 2
  lacp_time: fast

member: p0: current attached
  port_id: 1
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 1
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 3
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation synchronized collecting distributing

member: p1: current attached
  port_id: 2
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:55:aa:55:00:00
  actor sys_priority: 65534
  actor port_id: 2
  actor port_priority: 65535
  actor key: 2
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:66:aa:66:00:00
  partner sys_priority: 65534
  partner port_id: 4
  partner port_priority: 65535
  partner key: 4
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond1 ----
  status: active negotiated
  sys_id: aa:66:aa:66:00:00
  sys_priority: 65534
  aggregation key: 4
  lacp_time: fast

member: p2: current attached
  port_id: 3
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 3
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 1
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation synchronized collecting distributing

member: p3: current attached
  port_id: 4
  port_priority: 65535
  may_enable: true

  actor sys_id: aa:66:aa:66:00:00
  actor sys_priority: 65534
  actor port_id: 4
  actor port_priority: 65535
  actor key: 4
  actor state: activity timeout aggregation synchronized collecting distributing

  partner sys_id: aa:55:aa:55:00:00
  partner sys_priority: 65534
  partner port_id: 2
  partner port_priority: 65535
  partner key: 2
  partner state: activity timeout aggregation synchronized collecting distributing
---- bond0 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p0: enabled
  may_enable: true

member p1: enabled
  active member
  may_enable: true

---- bond1 ----
bond_mode: balance-tcp
bond may use recirculation: yes, <del>
bond-hash-basis: 0
lb_output action: disabled, bond-id: -1
updelay: 0 ms
downdelay: 0 ms
lacp_status: negotiated
lacp_fallback_ab: false
active-backup primary: <none>
<active member mac del>

member p2: enabled
  may_enable: true

member p3: enabled
  active member
  may_enable: true

])

OVS_VSWITCHD_STOP
AT_CLEANUP

# test lacp liveness propagation - OF1.3.
AT_SETUP([lacp - liveness propagation - OF1.3])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow13 -P standard monitor br0 --detach --no-chdir --pidfile])
check_liveness () {
    printf '\n\n--- check_liveness %d ---\n\n\n' $1
    shift

        echo >>expout "OFPT_PORT_STATUS (OF1.3): MOD: 1(p0): addr:
     config:     0
     state:      $1
     speed: 0 Mbps now, 0 Mbps max"

        AT_CHECK(
      [[sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ *duration.*//
s/addr:[0-9a-fA-F:]*/addr:/' < monitor.log|grep -A3 "MOD: 1(p0)"|grep -ve --]],
      [0], [expout])
}
: > expout
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
# Set miss_send_len to 128, enabling port_status messages to our service connection.
ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080

# Create bond0 on br0 with members p0 and p1
#    and bond1 on br1 with members p2 and p3
# with p0 patched to p2 and p1 patched to p3.
AT_CHECK([ovs-vsctl add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p0 type=patch options:peer=p2 ofport_request=1 \
                    other-config:lacp-aggregation-key=2 -- \
   set interface p1 type=patch options:peer=p3 ofport_request=2 \
                    other-config:lacp-aggregation-key=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p2 p3 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p2 type=patch options:peer=p0 ofport_request=3 \
                    other-config:lacp-aggregation-key=4 -- \
   set interface p3 type=patch options:peer=p1 ofport_request=4 \
                    other-config:lacp-aggregation-key=4 --])

AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
ovs-appctl time/stop

# Wait for up to 5 (simulated) seconds, until LACP negotiation finishes.
i=0
while :; do
    ovs-appctl lacp/show bond0 > bond0
    AT_CAPTURE_FILE([bond0])
    ovs-appctl lacp/show bond1 > bond1
    AT_CAPTURE_FILE([bond1])
    if grep negotiated bond0 && grep negotiated bond1; then
        if grep expired bond0 || grep expired bond1; then
            :
        else
            break
        fi
    fi
    i=`expr $i + 1`
    if test $i = 50; then
        AT_FAIL_IF([:])
    fi
    ovs-appctl time/warp 100
done
check_liveness 1 LIVE

# Makes LACP state "expired" for p0 and p2.
AT_CHECK([ovs-vsctl \
-- add-port br0 null0 -- set int null0 type=patch options:peer=p2 -- set int p2 options:peer=null0 \
-- add-port br1 null1 -- set int null1 type=patch options:peer=p0 -- set int p0 options:peer=null1])

# Wait 4 more simulated seconds.  The LACP state should become "defaulted" for p0 and p2.
ovs-appctl time/warp 4100 100
check_liveness 3 0

# Reconnect the patch link between p0 and p2 to allow traffic between the ports.
AT_CHECK([ovs-vsctl \
-- del-port null0 -- set int p2 options:peer=p0 \
-- del-port null1 -- set int p0 options:peer=p2])

# Wait for 30 more seconds (LACP_SLOW_TIME_TX) for the lacp to renegotiate
ovs-appctl time/warp 30100 100
check_liveness 3 LIVE

OVS_VSWITCHD_STOP
AT_CLEANUP

# test lacp liveness propagation - OF1.4.
AT_SETUP([lacp - liveness propagation - OF1.4])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow14 -P standard monitor br0 --detach --no-chdir --pidfile])
check_liveness () {
    printf '\n\n--- check_liveness %d ---\n\n\n' $1
    shift

        echo >>expout "OFPT_PORT_STATUS (OF1.4): MOD: 1(p0): addr:
     config:     0
     state:      $1
     speed: 0 Mbps now, 0 Mbps max"

        AT_CHECK(
      [[sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ *duration.*//
s/addr:[0-9a-fA-F:]*/addr:/' < monitor.log|grep -A3 "MOD: 1(p0)"|grep -ve --]],
      [0], [expout])
}
: > expout
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
# Set miss_send_len to 128, enabling port_status messages to our service connection.
ovs-appctl -t ovs-ofctl ofctl/send 0509000c0123456700000080

# Create bond0 on br0 with members p0 and p1
#    and bond1 on br1 with members p2 and p3
# with p0 patched to p2 and p1 patched to p3.
AT_CHECK([ovs-vsctl add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p0 type=patch options:peer=p2 ofport_request=1 \
                    other-config:lacp-aggregation-key=2 -- \
   set interface p1 type=patch options:peer=p3 ofport_request=2 \
                    other-config:lacp-aggregation-key=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p2 p3 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p2 type=patch options:peer=p0 ofport_request=3 \
                    other-config:lacp-aggregation-key=4 -- \
   set interface p3 type=patch options:peer=p1 ofport_request=4 \
                    other-config:lacp-aggregation-key=4 --])

AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
ovs-appctl time/stop

# Wait for up to 5 (simulated) seconds, until LACP negotiation finishes.
i=0
while :; do
    ovs-appctl lacp/show bond0 > bond0
    AT_CAPTURE_FILE([bond0])
    ovs-appctl lacp/show bond1 > bond1
    AT_CAPTURE_FILE([bond1])
    if grep negotiated bond0 && grep negotiated bond1; then
        if grep expired bond0 || grep expired bond1; then
            :
        else
            break
        fi
    fi
    i=`expr $i + 1`
    if test $i = 50; then
        AT_FAIL_IF([:])
    fi
    ovs-appctl time/warp 100
done
check_liveness 1 LIVE

# Makes LACP state "expired" for p0 and p2.
AT_CHECK([ovs-vsctl \
-- add-port br0 null0 -- set int null0 type=patch options:peer=p2 -- set int p2 options:peer=null0 \
-- add-port br1 null1 -- set int null1 type=patch options:peer=p0 -- set int p0 options:peer=null1])

# Wait 4 more simulated seconds.  The LACP state should become "defaulted" for p0 and p2.
ovs-appctl time/warp 4100 100
check_liveness 3 0

# Reconnect the patch link between p0 and p2 to allow traffic between the ports.
AT_CHECK([ovs-vsctl \
-- del-port null0 -- set int p2 options:peer=p0 \
-- del-port null1 -- set int p0 options:peer=p2])

# Wait for 30 more seconds (LACP_SLOW_TIME_TX) for the lacp to renegotiate
ovs-appctl time/warp 30100 100
check_liveness 3 LIVE

OVS_VSWITCHD_STOP
AT_CLEANUP

# test lacp liveness propagation - OF1.5.
AT_SETUP([lacp - liveness propagation - OF1.5])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow15 -P standard monitor br0 --detach --no-chdir --pidfile])
check_liveness () {
    printf '\n\n--- check_liveness %d ---\n\n\n' $1
    shift

        echo >>expout "OFPT_PORT_STATUS (OF1.5): MOD: 1(p0): addr:
     config:     0
     state:      $1
     speed: 0 Mbps now, 0 Mbps max"

        AT_CHECK(
      [[sed '
s/ (xid=0x[0-9a-fA-F]*)//
s/ *duration.*//
s/addr:[0-9a-fA-F:]*/addr:/' < monitor.log|grep -A3 "MOD: 1(p0)"|grep -ve --]],
      [0], [expout])
}
: > expout
ovs-appctl -t ovs-ofctl ofctl/barrier
ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
# Set miss_send_len to 128, enabling port_status messages to our service connection.
ovs-appctl -t ovs-ofctl ofctl/send 0609000c0123456700000080

# Create bond0 on br0 with members p0 and p1
#    and bond1 on br1 with members p2 and p3
# with p0 patched to p2 and p1 patched to p3.
AT_CHECK([ovs-vsctl add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p0 type=patch options:peer=p2 ofport_request=1 \
                    other-config:lacp-aggregation-key=2 -- \
   set interface p1 type=patch options:peer=p3 ofport_request=2 \
                    other-config:lacp-aggregation-key=2 -- \
   add-br br1 -- \
   set bridge br1 other-config:hwaddr=aa:66:aa:66:00:00 -- \
   set bridge br1 datapath-type=dummy other-config:datapath-id=1234 \
                  fail-mode=secure -- \
   add-bond br1 bond1 p2 p3 bond_mode=balance-tcp lacp=active \
                            other-config:lacp-time=fast \
                            other-config:bond-rebalance-interval=0 -- \
   set interface p2 type=patch options:peer=p0 ofport_request=3 \
                    other-config:lacp-aggregation-key=4 -- \
   set interface p3 type=patch options:peer=p1 ofport_request=4 \
                    other-config:lacp-aggregation-key=4 --])

AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK
])
ovs-appctl time/stop

# Wait for up to 5 (simulated) seconds, until LACP negotiation finishes.
i=0
while :; do
    ovs-appctl lacp/show bond0 > bond0
    AT_CAPTURE_FILE([bond0])
    ovs-appctl lacp/show bond1 > bond1
    AT_CAPTURE_FILE([bond1])
    if grep negotiated bond0 && grep negotiated bond1; then
        if grep expired bond0 || grep expired bond1; then
            :
        else
            break
        fi
    fi
    i=`expr $i + 1`
    if test $i = 50; then
        AT_FAIL_IF([:])
    fi
    ovs-appctl time/warp 100
done
check_liveness 1 LIVE

# Makes LACP state "expired" for p0 and p2.
AT_CHECK([ovs-vsctl \
-- add-port br0 null0 -- set int null0 type=patch options:peer=p2 -- set int p2 options:peer=null0 \
-- add-port br1 null1 -- set int null1 type=patch options:peer=p0 -- set int p0 options:peer=null1])

# Wait 4 more simulated seconds.  The LACP state should become "defaulted" for p0 and p2.
ovs-appctl time/warp 4100 100
check_liveness 3 0

# Reconnect the patch link between p0 and p2 to allow traffic between the ports.
AT_CHECK([ovs-vsctl \
-- del-port null0 -- set int p2 options:peer=p0 \
-- del-port null1 -- set int p0 options:peer=p2])

# Wait for 30 more seconds (LACP_SLOW_TIME_TX) for the lacp to renegotiate
ovs-appctl time/warp 30100 100
check_liveness 3 LIVE

OVS_VSWITCHD_STOP
AT_CLEANUP
