This allows testing functionality that requires connectivity between multiple bridges, such as bonding, LACP, and CFM.
This commit adds an example use to test basic LACP negotiation. Signed-off-by: Ben Pfaff <b...@nicira.com> --- lib/netdev-dummy.c | 81 ++++++++++- tests/lacp.at | 428 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 506 insertions(+), 3 deletions(-) diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c index 9b9e251..5636854 100644 --- a/lib/netdev-dummy.c +++ b/lib/netdev-dummy.c @@ -42,6 +42,7 @@ struct netdev_dev_dummy { struct netdev_stats stats; enum netdev_flags flags; unsigned int change_seq; + char *peer; struct list devs; /* List of child "netdev_dummy"s. */ }; @@ -67,6 +68,8 @@ static int netdev_dev_dummy_update_flags(struct netdev_dev_dummy *, enum netdev_flags off, enum netdev_flags on, enum netdev_flags *old_flagsp); +static int netdev_dummy_queue_packet(struct netdev_dev_dummy *, + const void *data, size_t size); static bool is_dummy_class(const struct netdev_class *class) @@ -125,10 +128,44 @@ netdev_dummy_destroy(struct netdev_dev *netdev_dev_) shash_find_and_delete(&dummy_netdev_devs, netdev_dev_get_name(netdev_dev_)); + free(netdev_dev->peer); free(netdev_dev); } static int +netdev_dummy_set_config(struct netdev_dev *netdev_dev_, + const struct smap *args) +{ + struct netdev_dev_dummy *netdev_dev = netdev_dev_dummy_cast(netdev_dev_); + const char *name = netdev_dev_get_name(netdev_dev_); + const struct smap_node *node; + const char *peer; + + SMAP_FOR_EACH (node, args) { + if (strcmp(node->key, "peer")) { + VLOG_WARN("%s: unknown option '%s'", name, node->key); + return EINVAL; + } + } + + free(netdev_dev->peer); + peer = smap_get(args, "peer"); + netdev_dev->peer = peer ? xstrdup(peer) : NULL; + return 0; +} + +static int +netdev_dummy_get_config(struct netdev_dev *netdev_dev_, struct smap *args) +{ + struct netdev_dev_dummy *netdev_dev = netdev_dev_dummy_cast(netdev_dev_); + + if (netdev_dev->peer) { + smap_add(args, "peer", netdev_dev->peer); + } + return 0; +} + +static int netdev_dummy_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp) { struct netdev_dev_dummy *netdev_dev = netdev_dev_dummy_cast(netdev_dev_); @@ -205,6 +242,44 @@ netdev_dummy_drain(struct netdev *netdev_) } static int +netdev_dummy_send(struct netdev *netdev, const void *buffer, size_t size) +{ + struct netdev_dev_dummy *dev = + netdev_dev_dummy_cast(netdev_get_dev(netdev)); + + if (size < ETH_HEADER_LEN) { + return EMSGSIZE; + } else { + const struct eth_header *eth = buffer; + int max_size; + + max_size = dev->mtu + ETH_HEADER_LEN; + if (eth->eth_type == htons(ETH_TYPE_VLAN)) { + max_size += VLAN_HEADER_LEN; + } + if (size > max_size) { + return EMSGSIZE; + } + } + + if (dev->peer) { + struct netdev_dev_dummy *peer; + + peer = shash_find_data(&dummy_netdev_devs, dev->peer); + if (peer) { + netdev_dummy_queue_packet(peer, buffer, size); + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5); + + VLOG_INFO_RL(&rl, "%s: configured peer %s does not exist", + netdev_get_name(netdev), dev->peer); + } + } + + return 0; +} + +static int netdev_dummy_set_etheraddr(struct netdev *netdev, const uint8_t mac[ETH_ADDR_LEN]) { @@ -324,8 +399,8 @@ static const struct netdev_class dummy_class = { netdev_dummy_create, netdev_dummy_destroy, - NULL, /* get_config */ - NULL, /* set_config */ + netdev_dummy_get_config, + netdev_dummy_set_config, netdev_dummy_open, netdev_dummy_close, @@ -335,7 +410,7 @@ static const struct netdev_class dummy_class = { netdev_dummy_recv_wait, netdev_dummy_drain, - NULL, /* send */ + netdev_dummy_send, /* send */ NULL, /* send_wait */ netdev_dummy_set_etheraddr, diff --git a/tests/lacp.at b/tests/lacp.at index d473d70..e9c1948 100644 --- a/tests/lacp.at +++ b/tests/lacp.at @@ -117,3 +117,431 @@ slave p2: disabled ]) OVS_VSWITCHD_STOP AT_CLEANUP + +AT_SETUP([lacp - negotiation]) +# Create bond0 on br0 with interfaces p0 and p1 +# and bond1 on br1 with interfaces 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=dummy options:peer=p2 -- \ + set interface p1 type=dummy options:peer=p3 -- \ + 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=dummy options:peer=p0 -- \ + set interface p3 type=dummy options:peer=p1]) + +AT_CHECK([ovs-appctl netdev-dummy/set-admin-state up], 0, [OK +]) + +# 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 +ovs-appctl bond/show bond1], [0], [stdout]) +AT_CHECK([sed '/active slave/d' stdout], [0], [dnl +---- bond0 ---- + status: active negotiated + sys_id: aa:55:aa:55:00:00 + sys_priority: 65534 + aggregation key: 1 + lacp_time: fast + +slave: p0: 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: 1 + actor state: activity timeout aggregation synchronized collecting distributing + + partner sys_id: aa:66:aa:66: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 + +slave: p1: 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: 1 + 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: 2 + 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: 2 + lacp_time: fast + +slave: p2: current attached + port_id: 2 + port_priority: 65535 + may_enable: true + + actor sys_id: aa:66:aa:66: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:55:aa:55:00:00 + partner sys_priority: 65534 + partner port_id: 2 + partner port_priority: 65535 + partner key: 1 + partner state: activity timeout aggregation synchronized collecting distributing + +slave: p3: 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: 2 + 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: 1 + partner state: activity timeout aggregation synchronized collecting distributing +---- bond0 ---- +bond_mode: balance-tcp +bond-hash-basis: 0 +updelay: 0 ms +downdelay: 0 ms +lacp_status: negotiated + +slave p0: enabled + may_enable: true + +slave p1: enabled + may_enable: true + +---- bond1 ---- +bond_mode: balance-tcp +bond-hash-basis: 0 +updelay: 0 ms +downdelay: 0 ms +lacp_status: negotiated + +slave p2: enabled + may_enable: true + +slave p3: enabled + may_enable: true + +]) +AT_CHECK([grep 'active slave' stdout], [0], [dnl + active slave + active slave +]) + +# Drop 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 remove interface p0 options peer -- \ + remove interface p2 options peer]) +for i in `seq 0 40`; do ovs-appctl time/warp 100; done +AT_CHECK( + [ovs-appctl lacp/show bond0 +ovs-appctl lacp/show bond1 +ovs-appctl bond/show bond0 +ovs-appctl bond/show bond1], [0], [dnl +---- bond0 ---- + status: active negotiated + sys_id: aa:55:aa:55:00:00 + sys_priority: 65534 + aggregation key: 1 + lacp_time: fast + +slave: p0: expired attached + port_id: 2 + port_priority: 65535 + may_enable: false + + actor sys_id: aa:55:aa:55:00:00 + actor sys_priority: 65534 + actor port_id: 2 + actor port_priority: 65535 + actor key: 1 + 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: 2 + partner port_priority: 65535 + partner key: 2 + partner state: activity timeout aggregation collecting distributing + +slave: p1: 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: 1 + 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: 2 + 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: 2 + lacp_time: fast + +slave: p2: expired attached + port_id: 2 + port_priority: 65535 + may_enable: false + + actor sys_id: aa:66:aa:66: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 expired + + partner sys_id: aa:55:aa:55:00:00 + partner sys_priority: 65534 + partner port_id: 2 + partner port_priority: 65535 + partner key: 1 + partner state: activity timeout aggregation collecting distributing + +slave: p3: 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: 2 + 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: 1 + partner state: activity timeout aggregation synchronized collecting distributing +---- bond0 ---- +bond_mode: balance-tcp +bond-hash-basis: 0 +updelay: 0 ms +downdelay: 0 ms +lacp_status: negotiated + +slave p0: disabled + may_enable: false + +slave p1: enabled + active slave + may_enable: true + +---- bond1 ---- +bond_mode: balance-tcp +bond-hash-basis: 0 +updelay: 0 ms +downdelay: 0 ms +lacp_status: negotiated + +slave p2: disabled + may_enable: false + +slave p3: enabled + active slave + may_enable: true + +]) + +# Wait 4 more simulated seconds. The LACP state should become +# "defaulted" for p0 and p2. +for i in `seq 0 40`; do ovs-appctl time/warp 100; done +AT_CHECK( + [ovs-appctl lacp/show bond0 +ovs-appctl lacp/show bond1 +ovs-appctl bond/show bond0 +ovs-appctl bond/show bond1], [0], [dnl +---- bond0 ---- + status: active negotiated + sys_id: aa:55:aa:55:00:00 + sys_priority: 65534 + aggregation key: 1 + lacp_time: fast + +slave: p0: defaulted detached + port_id: 2 + port_priority: 65535 + may_enable: false + + actor sys_id: aa:55:aa:55:00:00 + actor sys_priority: 65534 + actor port_id: 2 + actor port_priority: 65535 + actor key: 1 + 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: + +slave: p1: 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: 1 + 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: 2 + 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: 2 + lacp_time: fast + +slave: p2: defaulted detached + port_id: 2 + port_priority: 65535 + may_enable: false + + actor sys_id: aa:66:aa:66:00:00 + actor sys_priority: 65534 + actor port_id: 2 + 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: + +slave: p3: 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: 2 + 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: 1 + partner state: activity timeout aggregation synchronized collecting distributing +---- bond0 ---- +bond_mode: balance-tcp +bond-hash-basis: 0 +updelay: 0 ms +downdelay: 0 ms +lacp_status: negotiated + +slave p0: disabled + may_enable: false + +slave p1: enabled + active slave + may_enable: true + +---- bond1 ---- +bond_mode: balance-tcp +bond-hash-basis: 0 +updelay: 0 ms +downdelay: 0 ms +lacp_status: negotiated + +slave p2: disabled + may_enable: false + +slave p3: enabled + active slave + may_enable: true + +]) +OVS_VSWITCHD_STOP +AT_CLEANUP -- 1.7.2.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev