mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
Eliminate use of term "slave" in bond, LACP, and bundle contexts.
The new term is "member". Most of these changes should not change user-visible behavior. One place where they do is in "ovs-ofctl dump-flows", which will now output "members:..." inside "bundle" actions instead of "slaves:...". I don't expect this to cause real problems in most systems. The old syntax is still supported on input for backward compatibility. Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com>
This commit is contained in:
parent
f51cf36d86
commit
91fc374a9c
@ -25,22 +25,22 @@
|
|||||||
Bonding
|
Bonding
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Bonding allows two or more interfaces (the "slaves") to share network traffic.
|
Bonding allows two or more interfaces, its "members", to share network traffic.
|
||||||
From a high-level point of view, bonded interfaces act like a single port, but
|
From a high-level point of view, bonded interfaces act like a single port, but
|
||||||
they have the bandwidth of multiple network devices, e.g. two 1 GB physical
|
they have the bandwidth of multiple network devices, e.g. two 1 GB physical
|
||||||
interfaces act like a single 2 GB interface. Bonds also increase robustness:
|
interfaces act like a single 2 GB interface. Bonds also increase robustness:
|
||||||
the bonded port does not go down as long as at least one of its slaves is up.
|
the bonded port does not go down as long as at least one of its members is up.
|
||||||
|
|
||||||
In vswitchd, a bond always has at least two slaves (and may have more). If a
|
In vswitchd, a bond always has at least two members (and may have more). If a
|
||||||
configuration error, etc. would cause a bond to have only one slave, the port
|
configuration error, etc. would cause a bond to have only one member, the port
|
||||||
becomes an ordinary port, not a bonded port, and none of the special features
|
becomes an ordinary port, not a bonded port, and none of the special features
|
||||||
of bonded ports described in this section apply.
|
of bonded ports described in this section apply.
|
||||||
|
|
||||||
There are many forms of bonding of which ovs-vswitchd implements only a few.
|
There are many forms of bonding of which ovs-vswitchd implements only a few.
|
||||||
The most complex bond ovs-vswitchd implements is called "source load balancing"
|
The most complex bond ovs-vswitchd implements is called "source load balancing"
|
||||||
or SLB bonding. SLB bonding divides traffic among the slaves based on the
|
or SLB bonding. SLB bonding divides traffic among the members based on
|
||||||
Ethernet source address. This is useful only if the traffic over the bond has
|
the Ethernet source address. This is useful only if the traffic over the bond
|
||||||
multiple Ethernet source addresses, for example if network traffic from
|
has multiple Ethernet source addresses, for example if network traffic from
|
||||||
multiple VMs are multiplexed over the bond.
|
multiple VMs are multiplexed over the bond.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@ -50,89 +50,90 @@ multiple VMs are multiplexed over the bond.
|
|||||||
specified.
|
specified.
|
||||||
|
|
||||||
|
|
||||||
Enabling and Disabling Slaves
|
Enabling and Disabling Members
|
||||||
-----------------------------
|
------------------------------
|
||||||
|
|
||||||
When a bond is created, a slave is initially enabled or disabled based on
|
When a bond is created, a member is initially enabled or disabled based
|
||||||
whether carrier is detected on the NIC (see ``iface_create()``). After that, a
|
on whether carrier is detected on the NIC (see ``iface_create()``). After
|
||||||
slave is disabled if its carrier goes down for a period of time longer than the
|
that, a member is disabled if its carrier goes down for a period of time
|
||||||
downdelay, and it is enabled if carrier comes up for longer than the updelay
|
longer than the downdelay, and it is enabled if carrier comes up for longer
|
||||||
(see ``bond_link_status_update()``). There is one exception where the updelay
|
than the updelay (see ``bond_link_status_update()``). There is one exception
|
||||||
is skipped: if no slaves at all are currently enabled, then the first slave on
|
where the updelay is skipped: if no members at all are currently
|
||||||
which carrier comes up is enabled immediately.
|
enabled, then the first member on which carrier comes up is enabled
|
||||||
|
immediately.
|
||||||
|
|
||||||
The updelay should be set to a time longer than the STP forwarding delay of the
|
The updelay should be set to a time longer than the STP forwarding delay of the
|
||||||
physical switch to which the bond port is connected (if STP is enabled on that
|
physical switch to which the bond port is connected (if STP is enabled on that
|
||||||
switch). Otherwise, the slave will be enabled, and load may be shifted to it,
|
switch). Otherwise, the member will be enabled, and load may be shifted
|
||||||
before the physical switch starts forwarding packets on that port, which can
|
to it, before the physical switch starts forwarding packets on that port, which
|
||||||
cause some data to be "blackholed" for a time. The exception for a single
|
can cause some data to be dropped for a time. The exception for a single
|
||||||
enabled slave does not cause any problem in this regard because when no slaves
|
enabled member does not cause any problem in this regard because when no
|
||||||
are enabled all output packets are blackholed anyway.
|
members are enabled all output packets are dropped anyway.
|
||||||
|
|
||||||
When a slave becomes disabled, the vswitch immediately chooses a new output
|
When a member becomes disabled, the vswitch immediately chooses a new
|
||||||
port for traffic that was destined for that slave (see
|
output port for traffic that was destined for that member (see
|
||||||
``bond_enable_slave()``). It also sends a "gratuitous learning packet",
|
``bond_enable_member()``). It also sends a "gratuitous learning packet",
|
||||||
specifically a RARP, on the bond port (on the newly chosen slave) for each MAC
|
specifically a RARP, on the bond port (on the newly chosen member) for
|
||||||
address that the vswitch has learned on a port other than the bond (see
|
each MAC address that the vswitch has learned on a port other than the bond
|
||||||
``bundle_send_learning_packets()``), to teach the physical switch that the new
|
(see ``bundle_send_learning_packets()``), to teach the physical switch that the
|
||||||
slave should be used in place of the one that is now disabled. (This behavior
|
new member should be used in place of the one that is now disabled.
|
||||||
probably makes sense only for a vswitch that has only one port (the bond)
|
(This behavior probably makes sense only for a vswitch that has only one port
|
||||||
connected to a physical switch; vswitchd should probably provide a way to
|
(the bond) connected to a physical switch; vswitchd should probably provide a
|
||||||
disable or configure it in other scenarios.)
|
way to disable or configure it in other scenarios.)
|
||||||
|
|
||||||
Bond Packet Input
|
Bond Packet Input
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Bonding accepts unicast packets on any bond slave. This can occasionally cause
|
Bonding accepts unicast packets on any member. This can occasionally
|
||||||
packet duplication for the first few packets sent to a given MAC, if the
|
cause packet duplication for the first few packets sent to a given MAC, if the
|
||||||
physical switch attached to the bond is flooding packets to that MAC because it
|
physical switch attached to the bond is flooding packets to that MAC because it
|
||||||
has not yet learned the correct slave for that MAC.
|
has not yet learned the correct member for that MAC.
|
||||||
|
|
||||||
Bonding only accepts multicast (and broadcast) packets on a single bond slave
|
Bonding only accepts multicast (and broadcast) packets on a single bond
|
||||||
(the "active slave") at any given time. Multicast packets received on other
|
member (the "active member") at any given time. Multicast
|
||||||
slaves are dropped. Otherwise, every multicast packet would be duplicated,
|
packets received on other members are dropped. Otherwise, every
|
||||||
once for every bond slave, because the physical switch attached to the bond
|
multicast packet would be duplicated, once for every bond member,
|
||||||
will flood those packets.
|
because the physical switch attached to the bond will flood those packets.
|
||||||
|
|
||||||
Bonding also drops received packets when the vswitch has learned that the
|
Bonding also drops received packets when the vswitch has learned that the
|
||||||
packet's MAC is on a port other than the bond port itself. This is because it
|
packet's MAC is on a port other than the bond port itself. This is because it
|
||||||
is likely that the vswitch itself sent the packet out the bond port on a
|
is likely that the vswitch itself sent the packet out the bond port on a
|
||||||
different slave and is now receiving the packet back. This occurs when the
|
different member and is now receiving the packet back. This occurs when
|
||||||
packet is multicast or the physical switch has not yet learned the MAC and is
|
the packet is multicast or the physical switch has not yet learned the MAC and
|
||||||
flooding it. However, the vswitch makes an exception to this rule for
|
is flooding it. However, the vswitch makes an exception to this rule for
|
||||||
broadcast ARP replies, which indicate that the MAC has moved to another switch,
|
broadcast ARP replies, which indicate that the MAC has moved to another switch,
|
||||||
probably due to VM migration. (ARP replies are normally unicast, so this
|
probably due to VM migration. (ARP replies are normally unicast, so this
|
||||||
exception does not match normal ARP replies. It will match the learning
|
exception does not match normal ARP replies. It will match the learning
|
||||||
packets sent on bond fail-over.)
|
packets sent on bond fail-over.)
|
||||||
|
|
||||||
The active slave is simply the first slave to be enabled after the bond is
|
The active member is simply the first member to be enabled after
|
||||||
created (see ``bond_choose_active_slave()``). If the active slave is disabled,
|
the bond is created (see ``bond_choose_active_member()``). If the active
|
||||||
then a new active slave is chosen among the slaves that remain active.
|
member is disabled, then a new active member is chosen among the
|
||||||
Currently due to the way that configuration works, this tends to be the
|
members that remain active. Currently due to the way that configuration
|
||||||
remaining slave whose interface name is first alphabetically, but this is by no
|
works, this tends to be the remaining member whose interface name is
|
||||||
means guaranteed.
|
first alphabetically, but this is by no means guaranteed.
|
||||||
|
|
||||||
Bond Packet Output
|
Bond Packet Output
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
When a packet is sent out a bond port, the bond slave actually used is selected
|
When a packet is sent out a bond port, the bond member actually used is
|
||||||
based on the packet's source MAC and VLAN tag (see ``bond_choose_output_slave()``).
|
selected based on the packet's source MAC and VLAN tag (see
|
||||||
In particular, the source MAC and VLAN tag are hashed into one of 256 values,
|
``bond_choose_output_member()``). In particular, the source MAC and VLAN tag
|
||||||
and that value is looked up in a hash table (the "bond hash") kept in the
|
are hashed into one of 256 values, and that value is looked up in a hash table
|
||||||
``bond_hash`` member of struct port. The hash table entry identifies a bond
|
(the "bond hash") kept in the ``bond_hash`` member of struct port. The hash
|
||||||
slave. If no bond slave has yet been chosen for that hash table entry,
|
table entry identifies a bond member. If no bond member has yet been chosen
|
||||||
vswitchd chooses one arbitrarily.
|
for that hash table entry, vswitchd chooses one arbitrarily.
|
||||||
|
|
||||||
Every 10 seconds, vswitchd rebalances the bond slaves (see
|
Every 10 seconds, vswitchd rebalances the bond members (see
|
||||||
``bond_rebalance()``). To rebalance, vswitchd examines the statistics for
|
``bond_rebalance()``). To rebalance, vswitchd examines the statistics for the
|
||||||
the number of bytes transmitted by each slave over approximately the past
|
number of bytes transmitted by each member over approximately the past
|
||||||
minute, with data sent more recently weighted more heavily than data sent less
|
minute, with data sent more recently weighted more heavily than data sent less
|
||||||
recently. It considers each of the slaves in order from most-loaded to
|
recently. It considers each of the members in order from most-loaded to
|
||||||
least-loaded. If highly loaded slave H is significantly more heavily loaded
|
least-loaded. If highly loaded member H is significantly more heavily
|
||||||
than the least-loaded slave L, and slave H carries at least two hashes, then
|
loaded than the least-loaded member L, and member H carries at
|
||||||
vswitchd shifts one of H's hashes to L. However, vswitchd will only shift a
|
least two hashes, then vswitchd shifts one of H's hashes to L. However,
|
||||||
hash from H to L if it will decrease the ratio of the load between H and L by
|
vswitchd will only shift a hash from H to L if it will decrease the ratio of
|
||||||
at least 0.1.
|
the load between H and L by at least 0.1.
|
||||||
|
|
||||||
Currently, "significantly more loaded" means that H must carry at least 1 Mbps
|
Currently, "significantly more loaded" means that H must carry at least 1 Mbps
|
||||||
more traffic, and that traffic must be at least 3% greater than L's.
|
more traffic, and that traffic must be at least 3% greater than L's.
|
||||||
@ -166,11 +167,11 @@ behavior on Open vSwitch.
|
|||||||
Active Backup Bonding
|
Active Backup Bonding
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Active Backup bonds send all traffic out one "active" slave until that slave
|
Active Backup bonds send all traffic out one "active" member until that
|
||||||
becomes unavailable. Since they are significantly less complicated than SLB
|
member becomes unavailable. Since they are significantly less
|
||||||
bonds, they are preferred when LACP is not an option. Additionally, they are
|
complicated than SLB bonds, they are preferred when LACP is not an option.
|
||||||
the only bond mode which supports attaching each slave to a different upstream
|
Additionally, they are the only bond mode which supports attaching each
|
||||||
switch.
|
member to a different upstream switch.
|
||||||
|
|
||||||
SLB Bonding
|
SLB Bonding
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
@ -195,15 +196,15 @@ SLB bonding has the following complications:
|
|||||||
This would cause packet duplication if not handled specially.
|
This would cause packet duplication if not handled specially.
|
||||||
|
|
||||||
Open vSwitch avoids packet duplication by accepting multicast and broadcast
|
Open vSwitch avoids packet duplication by accepting multicast and broadcast
|
||||||
packets on only the active slave, and dropping multicast and broadcast
|
packets on only the active member, and dropping multicast and
|
||||||
packets on all other slaves.
|
broadcast packets on all other members.
|
||||||
|
|
||||||
2. When Open vSwitch forwards a multicast or broadcast packet to a link in the
|
2. When Open vSwitch forwards a multicast or broadcast packet to a link in the
|
||||||
SLB bond other than the active slave, the remote switch will forward it to
|
SLB bond other than the active member, the remote switch will forward
|
||||||
all of the other links in the SLB bond, including the active slave. Without
|
it to all of the other links in the SLB bond, including the active
|
||||||
special handling, this would mean that Open vSwitch would forward a second
|
member. Without special handling, this would mean that Open vSwitch
|
||||||
copy of the packet to each switch port (other than the bond), including the
|
would forward a second copy of the packet to each switch port (other than
|
||||||
port that originated the packet.
|
the bond), including the port that originated the packet.
|
||||||
|
|
||||||
Open vSwitch deals with this case by dropping packets received on any SLB
|
Open vSwitch deals with this case by dropping packets received on any SLB
|
||||||
bonded link that have a source MAC+VLAN that has been learned on any other
|
bonded link that have a source MAC+VLAN that has been learned on any other
|
||||||
@ -226,11 +227,11 @@ SLB bonding has the following complications:
|
|||||||
4. Suppose that a MAC+VLAN moves from an SLB bond to another port (e.g. when a
|
4. Suppose that a MAC+VLAN moves from an SLB bond to another port (e.g. when a
|
||||||
VM is migrated from a different hypervisor to this one), that the MAC+VLAN
|
VM is migrated from a different hypervisor to this one), that the MAC+VLAN
|
||||||
emits a gratuitous ARP, and that Open vSwitch forwards that gratuitous ARP
|
emits a gratuitous ARP, and that Open vSwitch forwards that gratuitous ARP
|
||||||
to a link in the SLB bond other than the active slave. The remote switch
|
to a link in the SLB bond other than the active member. The remote
|
||||||
will forward the gratuitous ARP to all of the other links in the SLB bond,
|
switch will forward the gratuitous ARP to all of the other links in the SLB
|
||||||
including the active slave. Without additional special handling, this would
|
bond, including the active member. Without additional special
|
||||||
mean that Open vSwitch would learn that the MAC+VLAN was located on the SLB
|
handling, this would mean that Open vSwitch would learn that the MAC+VLAN
|
||||||
bond, as a consequence of rule #3.
|
was located on the SLB bond, as a consequence of rule #3.
|
||||||
|
|
||||||
Open vSwitch avoids this problem by "locking" the MAC learning table entry
|
Open vSwitch avoids this problem by "locking" the MAC learning table entry
|
||||||
for a MAC+VLAN from which a gratuitous ARP was received from a non-SLB bond
|
for a MAC+VLAN from which a gratuitous ARP was received from a non-SLB bond
|
||||||
|
@ -42,8 +42,8 @@ concordance, indexed by the area of the source tree:
|
|||||||
datapath/ vport ---
|
datapath/ vport ---
|
||||||
vswitchd/ iface port
|
vswitchd/ iface port
|
||||||
ofproto/ port bundle
|
ofproto/ port bundle
|
||||||
ofproto/bond.c slave bond
|
ofproto/bond.c member bond
|
||||||
lib/lacp.c slave lacp
|
lib/lacp.c member lacp
|
||||||
lib/netdev.c netdev ---
|
lib/netdev.c netdev ---
|
||||||
database Interface Port
|
database Interface Port
|
||||||
|
|
||||||
|
4
NEWS
4
NEWS
@ -12,6 +12,8 @@ Post-v2.14.0
|
|||||||
- Terminology:
|
- Terminology:
|
||||||
* The terms "master" and "slave" have been replaced by "primary" and
|
* The terms "master" and "slave" have been replaced by "primary" and
|
||||||
"secondary", respectively, for OpenFlow connection roles.
|
"secondary", respectively, for OpenFlow connection roles.
|
||||||
|
* The term "slave" has been replaced by "member", for bonds, LACP, and
|
||||||
|
OpenFlow bundle actions.
|
||||||
|
|
||||||
|
|
||||||
v2.14.0 - 17 Aug 2020
|
v2.14.0 - 17 Aug 2020
|
||||||
@ -833,7 +835,7 @@ v2.4.0 - 20 Aug 2015
|
|||||||
The implementation has been tested successfully against the Ixia Automated
|
The implementation has been tested successfully against the Ixia Automated
|
||||||
Network Validation Library (ANVL).
|
Network Validation Library (ANVL).
|
||||||
- Stats are no longer updated on fake bond interface.
|
- Stats are no longer updated on fake bond interface.
|
||||||
- Keep active bond slave selection across OVS restart.
|
- Keep active bond interface selection across OVS restart.
|
||||||
- A simple wrapper script, 'ovs-docker', to integrate OVS with Docker
|
- A simple wrapper script, 'ovs-docker', to integrate OVS with Docker
|
||||||
containers. If and when there is a native integration of Open vSwitch
|
containers. If and when there is a native integration of Open vSwitch
|
||||||
with Docker, the wrapper script will be retired.
|
with Docker, the wrapper script will be retired.
|
||||||
|
2
debian/changelog
vendored
2
debian/changelog
vendored
@ -388,7 +388,7 @@ openvswitch (2.4.0-1) unstable; urgency=low
|
|||||||
The implementation has been tested successfully against the Ixia Automated
|
The implementation has been tested successfully against the Ixia Automated
|
||||||
Network Validation Library (ANVL).
|
Network Validation Library (ANVL).
|
||||||
- Stats are no longer updated on fake bond interface.
|
- Stats are no longer updated on fake bond interface.
|
||||||
- Keep active bond slave selection across OVS restart.
|
- Keep active bond member selection across OVS restart.
|
||||||
- A simple wrapper script, 'ovs-docker', to integrate OVS with Docker
|
- A simple wrapper script, 'ovs-docker', to integrate OVS with Docker
|
||||||
containers. If and when there is a native integration of Open vSwitch
|
containers. If and when there is a native integration of Open vSwitch
|
||||||
with Docker, the wrapper script will be retired.
|
with Docker, the wrapper script will be retired.
|
||||||
|
4
debian/ifupdown.sh
vendored
4
debian/ifupdown.sh
vendored
@ -65,9 +65,9 @@ if [ "${MODE}" = "start" ]; then
|
|||||||
${OVS_EXTRA+-- $OVS_EXTRA}
|
${OVS_EXTRA+-- $OVS_EXTRA}
|
||||||
|
|
||||||
ip link set "${IFACE}" up
|
ip link set "${IFACE}" up
|
||||||
for slave in ${IF_OVS_BONDS}
|
for member in ${IF_OVS_BONDS}
|
||||||
do
|
do
|
||||||
ip link set "${slave}" up
|
ip link set "${member}" up
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
OVSPatchPort)
|
OVSPatchPort)
|
||||||
|
@ -66,7 +66,7 @@ struct vl_mff_map;
|
|||||||
OFPACT(CONTROLLER, ofpact_controller, userdata, "controller") \
|
OFPACT(CONTROLLER, ofpact_controller, userdata, "controller") \
|
||||||
OFPACT(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \
|
OFPACT(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \
|
||||||
OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \
|
OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \
|
||||||
OFPACT(BUNDLE, ofpact_bundle, slaves, "bundle") \
|
OFPACT(BUNDLE, ofpact_bundle, members, "bundle") \
|
||||||
\
|
\
|
||||||
/* Header changes. */ \
|
/* Header changes. */ \
|
||||||
OFPACT(SET_FIELD, ofpact_set_field, ofpact, "set_field") \
|
OFPACT(SET_FIELD, ofpact_set_field, ofpact, "set_field") \
|
||||||
@ -364,24 +364,24 @@ struct ofpact_output_trunc {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Bundle slave choice algorithm to apply.
|
/* Bundle member choice algorithm to apply.
|
||||||
*
|
*
|
||||||
* In the descriptions below, 'slaves' is the list of possible slaves in the
|
* In the descriptions below, 'members' is the list of possible members in the
|
||||||
* order they appear in the OpenFlow action. */
|
* order they appear in the OpenFlow action. */
|
||||||
enum nx_bd_algorithm {
|
enum nx_bd_algorithm {
|
||||||
/* Chooses the first live slave listed in the bundle.
|
/* Chooses the first live member listed in the bundle.
|
||||||
*
|
*
|
||||||
* O(n_slaves) performance. */
|
* O(n_members) performance. */
|
||||||
NX_BD_ALG_ACTIVE_BACKUP = 0,
|
NX_BD_ALG_ACTIVE_BACKUP = 0,
|
||||||
|
|
||||||
/* Highest Random Weight.
|
/* Highest Random Weight.
|
||||||
*
|
*
|
||||||
* for i in [0,n_slaves):
|
* for i in [0,n_members):
|
||||||
* weights[i] = hash(flow, i)
|
* weights[i] = hash(flow, i)
|
||||||
* slave = { slaves[i] such that weights[i] >= weights[j] for all j != i }
|
* member = { members[i] such that weights[i] >= weights[j] for all j != i }
|
||||||
*
|
*
|
||||||
* Redistributes 1/n_slaves of traffic when a slave's liveness changes.
|
* Redistributes 1/n_members of traffic when a member's liveness changes.
|
||||||
* O(n_slaves) performance.
|
* O(n_members) performance.
|
||||||
*
|
*
|
||||||
* Uses the 'fields' and 'basis' parameters. */
|
* Uses the 'fields' and 'basis' parameters. */
|
||||||
NX_BD_ALG_HRW = 1
|
NX_BD_ALG_HRW = 1
|
||||||
@ -394,7 +394,7 @@ struct ofpact_bundle {
|
|||||||
OFPACT_PADDED_MEMBERS(
|
OFPACT_PADDED_MEMBERS(
|
||||||
struct ofpact ofpact;
|
struct ofpact ofpact;
|
||||||
|
|
||||||
/* Slave choice algorithm to apply to hash value. */
|
/* Member choice algorithm to apply to hash value. */
|
||||||
enum nx_bd_algorithm algorithm;
|
enum nx_bd_algorithm algorithm;
|
||||||
|
|
||||||
/* What fields to hash and how. */
|
/* What fields to hash and how. */
|
||||||
@ -403,10 +403,12 @@ struct ofpact_bundle {
|
|||||||
|
|
||||||
struct mf_subfield dst;
|
struct mf_subfield dst;
|
||||||
|
|
||||||
/* Slaves for output. */
|
bool compat_syntax;
|
||||||
unsigned int n_slaves;
|
|
||||||
|
/* Members for output. */
|
||||||
|
unsigned int n_members;
|
||||||
);
|
);
|
||||||
ofp_port_t slaves[];
|
ofp_port_t members[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* OFPACT_SET_VLAN_VID.
|
/* OFPACT_SET_VLAN_VID.
|
||||||
|
101
lib/bundle.c
101
lib/bundle.c
@ -39,14 +39,14 @@ VLOG_DEFINE_THIS_MODULE(bundle);
|
|||||||
|
|
||||||
static ofp_port_t
|
static ofp_port_t
|
||||||
execute_ab(const struct ofpact_bundle *bundle,
|
execute_ab(const struct ofpact_bundle *bundle,
|
||||||
bool (*slave_enabled)(ofp_port_t ofp_port, void *aux), void *aux)
|
bool (*member_enabled)(ofp_port_t ofp_port, void *aux), void *aux)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
ofp_port_t slave = bundle->slaves[i];
|
ofp_port_t member = bundle->members[i];
|
||||||
if (slave_enabled(slave, aux)) {
|
if (member_enabled(member, aux)) {
|
||||||
return slave;
|
return member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,12 +56,12 @@ execute_ab(const struct ofpact_bundle *bundle,
|
|||||||
static ofp_port_t
|
static ofp_port_t
|
||||||
execute_hrw(const struct ofpact_bundle *bundle,
|
execute_hrw(const struct ofpact_bundle *bundle,
|
||||||
const struct flow *flow, struct flow_wildcards *wc,
|
const struct flow *flow, struct flow_wildcards *wc,
|
||||||
bool (*slave_enabled)(ofp_port_t ofp_port, void *aux), void *aux)
|
bool (*member_enabled)(ofp_port_t ofp_port, void *aux), void *aux)
|
||||||
{
|
{
|
||||||
uint32_t flow_hash, best_hash;
|
uint32_t flow_hash, best_hash;
|
||||||
int best, i;
|
int best, i;
|
||||||
|
|
||||||
if (bundle->n_slaves > 1) {
|
if (bundle->n_members > 1) {
|
||||||
flow_mask_hash_fields(flow, wc, bundle->fields);
|
flow_mask_hash_fields(flow, wc, bundle->fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,8 +69,8 @@ execute_hrw(const struct ofpact_bundle *bundle,
|
|||||||
best = -1;
|
best = -1;
|
||||||
best_hash = 0;
|
best_hash = 0;
|
||||||
|
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
if (slave_enabled(bundle->slaves[i], aux)) {
|
if (member_enabled(bundle->members[i], aux)) {
|
||||||
uint32_t hash = hash_2words(i, flow_hash);
|
uint32_t hash = hash_2words(i, flow_hash);
|
||||||
|
|
||||||
if (best < 0 || hash > best_hash) {
|
if (best < 0 || hash > best_hash) {
|
||||||
@ -80,25 +80,25 @@ execute_hrw(const struct ofpact_bundle *bundle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return best >= 0 ? bundle->slaves[best] : OFPP_NONE;
|
return best >= 0 ? bundle->members[best] : OFPP_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Executes 'bundle' on 'flow'. Sets fields in 'wc' that were used to
|
/* Executes 'bundle' on 'flow'. Sets fields in 'wc' that were used to
|
||||||
* calculate the result. Uses 'slave_enabled' to determine if the slave
|
* calculate the result. Uses 'member_enabled' to determine if the member
|
||||||
* designated by 'ofp_port' is up. Returns the chosen slave, or
|
* designated by 'ofp_port' is up. Returns the chosen member, or
|
||||||
* OFPP_NONE if none of the slaves are acceptable. */
|
* OFPP_NONE if none of the members are acceptable. */
|
||||||
ofp_port_t
|
ofp_port_t
|
||||||
bundle_execute(const struct ofpact_bundle *bundle,
|
bundle_execute(const struct ofpact_bundle *bundle,
|
||||||
const struct flow *flow, struct flow_wildcards *wc,
|
const struct flow *flow, struct flow_wildcards *wc,
|
||||||
bool (*slave_enabled)(ofp_port_t ofp_port, void *aux),
|
bool (*member_enabled)(ofp_port_t ofp_port, void *aux),
|
||||||
void *aux)
|
void *aux)
|
||||||
{
|
{
|
||||||
switch (bundle->algorithm) {
|
switch (bundle->algorithm) {
|
||||||
case NX_BD_ALG_HRW:
|
case NX_BD_ALG_HRW:
|
||||||
return execute_hrw(bundle, flow, wc, slave_enabled, aux);
|
return execute_hrw(bundle, flow, wc, member_enabled, aux);
|
||||||
|
|
||||||
case NX_BD_ALG_ACTIVE_BACKUP:
|
case NX_BD_ALG_ACTIVE_BACKUP:
|
||||||
return execute_ab(bundle, slave_enabled, aux);
|
return execute_ab(bundle, member_enabled, aux);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
OVS_NOT_REACHED();
|
OVS_NOT_REACHED();
|
||||||
@ -119,21 +119,21 @@ bundle_check(const struct ofpact_bundle *bundle, ofp_port_t max_ports,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
ofp_port_t ofp_port = bundle->slaves[i];
|
ofp_port_t ofp_port = bundle->members[i];
|
||||||
|
|
||||||
if (ofp_port != OFPP_NONE) {
|
if (ofp_port != OFPP_NONE) {
|
||||||
enum ofperr error = ofpact_check_output_port(ofp_port, max_ports);
|
enum ofperr error = ofpact_check_output_port(ofp_port, max_ports);
|
||||||
if (error) {
|
if (error) {
|
||||||
VLOG_WARN_RL(&rl, "invalid slave %"PRIu32, ofp_port);
|
VLOG_WARN_RL(&rl, "invalid member %"PRIu32, ofp_port);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Controller slaves are unsupported due to the lack of a max_len
|
/* Controller members are unsupported due to the lack of a max_len
|
||||||
* argument. This may or may not change in the future. There doesn't
|
* argument. This may or may not change in the future. There doesn't
|
||||||
* seem to be a real-world use-case for supporting it. */
|
* seem to be a real-world use-case for supporting it. */
|
||||||
if (ofp_port == OFPP_CONTROLLER) {
|
if (ofp_port == OFPP_CONTROLLER) {
|
||||||
VLOG_WARN_RL(&rl, "unsupported controller slave");
|
VLOG_WARN_RL(&rl, "unsupported controller member");
|
||||||
return OFPERR_OFPBAC_BAD_OUT_PORT;
|
return OFPERR_OFPBAC_BAD_OUT_PORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,38 +150,39 @@ static char * OVS_WARN_UNUSED_RESULT
|
|||||||
bundle_parse__(const char *s, const struct ofputil_port_map *port_map,
|
bundle_parse__(const char *s, const struct ofputil_port_map *port_map,
|
||||||
char **save_ptr,
|
char **save_ptr,
|
||||||
const char *fields, const char *basis, const char *algorithm,
|
const char *fields, const char *basis, const char *algorithm,
|
||||||
const char *slave_type, const char *dst,
|
const char *member_type, const char *dst,
|
||||||
const char *slave_delim, struct ofpbuf *ofpacts)
|
const char *member_delim, struct ofpbuf *ofpacts)
|
||||||
{
|
{
|
||||||
struct ofpact_bundle *bundle;
|
struct ofpact_bundle *bundle;
|
||||||
|
|
||||||
if (!slave_delim) {
|
if (!member_delim) {
|
||||||
return xasprintf("%s: not enough arguments to bundle action", s);
|
return xasprintf("%s: not enough arguments to bundle action", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(slave_delim, "slaves")) {
|
if (strcasecmp(member_delim, "members")
|
||||||
return xasprintf("%s: missing slave delimiter, expected `slaves' "
|
&& strcasecmp(member_delim, "slaves")) {
|
||||||
"got `%s'", s, slave_delim);
|
return xasprintf("%s: missing member delimiter, expected `members', "
|
||||||
|
"got `%s'", s, member_delim);
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle = ofpact_put_BUNDLE(ofpacts);
|
bundle = ofpact_put_BUNDLE(ofpacts);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ofp_port_t slave_port;
|
ofp_port_t member_port;
|
||||||
char *slave;
|
char *member;
|
||||||
|
|
||||||
slave = strtok_r(NULL, ", []", save_ptr);
|
member = strtok_r(NULL, ", []", save_ptr);
|
||||||
if (!slave || bundle->n_slaves >= BUNDLE_MAX_SLAVES) {
|
if (!member || bundle->n_members >= BUNDLE_MAX_MEMBERS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ofputil_port_from_string(slave, port_map, &slave_port)) {
|
if (!ofputil_port_from_string(member, port_map, &member_port)) {
|
||||||
return xasprintf("%s: bad port number", slave);
|
return xasprintf("%s: bad port number", member);
|
||||||
}
|
}
|
||||||
ofpbuf_put(ofpacts, &slave_port, sizeof slave_port);
|
ofpbuf_put(ofpacts, &member_port, sizeof member_port);
|
||||||
|
|
||||||
bundle = ofpacts->header;
|
bundle = ofpacts->header;
|
||||||
bundle->n_slaves++;
|
bundle->n_members++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ofpbuf_oversized(ofpacts)) {
|
if (ofpbuf_oversized(ofpacts)) {
|
||||||
@ -217,8 +218,8 @@ bundle_parse__(const char *s, const struct ofputil_port_map *port_map,
|
|||||||
return xasprintf("%s: unknown algorithm `%s'", s, algorithm);
|
return xasprintf("%s: unknown algorithm `%s'", s, algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(slave_type, "ofport")) {
|
if (strcasecmp(member_type, "ofport")) {
|
||||||
return xasprintf("%s: unknown slave_type `%s'", s, slave_type);
|
return xasprintf("%s: unknown member_type `%s'", s, member_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst) {
|
if (dst) {
|
||||||
@ -245,7 +246,7 @@ char * OVS_WARN_UNUSED_RESULT
|
|||||||
bundle_parse(const char *s, const struct ofputil_port_map *port_map,
|
bundle_parse(const char *s, const struct ofputil_port_map *port_map,
|
||||||
struct ofpbuf *ofpacts)
|
struct ofpbuf *ofpacts)
|
||||||
{
|
{
|
||||||
char *fields, *basis, *algorithm, *slave_type, *slave_delim;
|
char *fields, *basis, *algorithm, *member_type, *member_delim;
|
||||||
char *tokstr, *save_ptr;
|
char *tokstr, *save_ptr;
|
||||||
char *error;
|
char *error;
|
||||||
|
|
||||||
@ -254,12 +255,12 @@ bundle_parse(const char *s, const struct ofputil_port_map *port_map,
|
|||||||
fields = strtok_r(tokstr, ", ", &save_ptr);
|
fields = strtok_r(tokstr, ", ", &save_ptr);
|
||||||
basis = strtok_r(NULL, ", ", &save_ptr);
|
basis = strtok_r(NULL, ", ", &save_ptr);
|
||||||
algorithm = strtok_r(NULL, ", ", &save_ptr);
|
algorithm = strtok_r(NULL, ", ", &save_ptr);
|
||||||
slave_type = strtok_r(NULL, ", ", &save_ptr);
|
member_type = strtok_r(NULL, ", ", &save_ptr);
|
||||||
slave_delim = strtok_r(NULL, ": ", &save_ptr);
|
member_delim = strtok_r(NULL, ": ", &save_ptr);
|
||||||
|
|
||||||
error = bundle_parse__(s, port_map,
|
error = bundle_parse__(s, port_map,
|
||||||
&save_ptr, fields, basis, algorithm, slave_type,
|
&save_ptr, fields, basis, algorithm, member_type,
|
||||||
NULL, slave_delim, ofpacts);
|
NULL, member_delim, ofpacts);
|
||||||
free(tokstr);
|
free(tokstr);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
@ -274,7 +275,7 @@ char * OVS_WARN_UNUSED_RESULT
|
|||||||
bundle_parse_load(const char *s, const struct ofputil_port_map *port_map,
|
bundle_parse_load(const char *s, const struct ofputil_port_map *port_map,
|
||||||
struct ofpbuf *ofpacts)
|
struct ofpbuf *ofpacts)
|
||||||
{
|
{
|
||||||
char *fields, *basis, *algorithm, *slave_type, *dst, *slave_delim;
|
char *fields, *basis, *algorithm, *member_type, *dst, *member_delim;
|
||||||
char *tokstr, *save_ptr;
|
char *tokstr, *save_ptr;
|
||||||
char *error;
|
char *error;
|
||||||
|
|
||||||
@ -283,13 +284,13 @@ bundle_parse_load(const char *s, const struct ofputil_port_map *port_map,
|
|||||||
fields = strtok_r(tokstr, ", ", &save_ptr);
|
fields = strtok_r(tokstr, ", ", &save_ptr);
|
||||||
basis = strtok_r(NULL, ", ", &save_ptr);
|
basis = strtok_r(NULL, ", ", &save_ptr);
|
||||||
algorithm = strtok_r(NULL, ", ", &save_ptr);
|
algorithm = strtok_r(NULL, ", ", &save_ptr);
|
||||||
slave_type = strtok_r(NULL, ", ", &save_ptr);
|
member_type = strtok_r(NULL, ", ", &save_ptr);
|
||||||
dst = strtok_r(NULL, ", ", &save_ptr);
|
dst = strtok_r(NULL, ", ", &save_ptr);
|
||||||
slave_delim = strtok_r(NULL, ": ", &save_ptr);
|
member_delim = strtok_r(NULL, ": ", &save_ptr);
|
||||||
|
|
||||||
error = bundle_parse__(s, port_map,
|
error = bundle_parse__(s, port_map,
|
||||||
&save_ptr, fields, basis, algorithm, slave_type,
|
&save_ptr, fields, basis, algorithm, member_type,
|
||||||
dst, slave_delim, ofpacts);
|
dst, member_delim, ofpacts);
|
||||||
|
|
||||||
free(tokstr);
|
free(tokstr);
|
||||||
|
|
||||||
@ -328,13 +329,13 @@ bundle_format(const struct ofpact_bundle *bundle,
|
|||||||
ds_put_char(s, ',');
|
ds_put_char(s, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
ds_put_format(s, "%sslaves:%s", colors.param, colors.end);
|
ds_put_format(s, "%smembers:%s", colors.param, colors.end);
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
if (i) {
|
if (i) {
|
||||||
ds_put_char(s, ',');
|
ds_put_char(s, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
ofputil_format_port(bundle->slaves[i], port_map, s);
|
ofputil_format_port(bundle->members[i], port_map, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds_put_format(s, "%s)%s", colors.paren, colors.end);
|
ds_put_format(s, "%s)%s", colors.paren, colors.end);
|
||||||
|
@ -40,11 +40,11 @@ struct ofputil_port_map;
|
|||||||
*
|
*
|
||||||
* See lib/ofp-actions.c for NXAST_BUNDLE specification. */
|
* See lib/ofp-actions.c for NXAST_BUNDLE specification. */
|
||||||
|
|
||||||
#define BUNDLE_MAX_SLAVES 2048
|
#define BUNDLE_MAX_MEMBERS 2048
|
||||||
|
|
||||||
ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
|
ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
|
||||||
struct flow_wildcards *wc,
|
struct flow_wildcards *wc,
|
||||||
bool (*slave_enabled)(ofp_port_t ofp_port, void *aux),
|
bool (*member_enabled)(ofp_port_t ofp_port, void *aux),
|
||||||
void *aux);
|
void *aux);
|
||||||
enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports,
|
enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports,
|
||||||
const struct match *);
|
const struct match *);
|
||||||
|
@ -780,8 +780,8 @@ cfm_process_heartbeat(struct cfm *cfm, const struct dp_packet *p)
|
|||||||
*
|
*
|
||||||
* Faults can cause a controller or Open vSwitch to make potentially
|
* Faults can cause a controller or Open vSwitch to make potentially
|
||||||
* expensive changes to the network topology. It seems prudent to trigger
|
* expensive changes to the network topology. It seems prudent to trigger
|
||||||
* them judiciously, especially when CFM is used to check slave status of
|
* them judiciously, especially when CFM is used to check status of bond
|
||||||
* bonds. Furthermore, faults can be maliciously triggered by crafting
|
* members. Furthermore, faults can be maliciously triggered by crafting
|
||||||
* unexpected CCMs. */
|
* unexpected CCMs. */
|
||||||
if (memcmp(ccm->maid, cfm->maid, sizeof ccm->maid)) {
|
if (memcmp(ccm->maid, cfm->maid, sizeof ccm->maid)) {
|
||||||
cfm->recv_fault |= CFM_FAULT_MAID;
|
cfm->recv_fault |= CFM_FAULT_MAID;
|
||||||
|
@ -629,9 +629,9 @@ struct tx_port {
|
|||||||
struct dp_netdev_rxq *output_pkts_rxqs[NETDEV_MAX_BURST];
|
struct dp_netdev_rxq *output_pkts_rxqs[NETDEV_MAX_BURST];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Contained by struct tx_bond 'slave_buckets'. */
|
/* Contained by struct tx_bond 'member_buckets'. */
|
||||||
struct slave_entry {
|
struct member_entry {
|
||||||
odp_port_t slave_id;
|
odp_port_t member_id;
|
||||||
atomic_ullong n_packets;
|
atomic_ullong n_packets;
|
||||||
atomic_ullong n_bytes;
|
atomic_ullong n_bytes;
|
||||||
};
|
};
|
||||||
@ -640,7 +640,7 @@ struct slave_entry {
|
|||||||
struct tx_bond {
|
struct tx_bond {
|
||||||
struct cmap_node node;
|
struct cmap_node node;
|
||||||
uint32_t bond_id;
|
uint32_t bond_id;
|
||||||
struct slave_entry slave_buckets[BOND_BUCKETS];
|
struct member_entry member_buckets[BOND_BUCKETS];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A set of properties for the current processing loop that is not directly
|
/* A set of properties for the current processing loop that is not directly
|
||||||
@ -1588,17 +1588,17 @@ dpif_netdev_bond_show(struct unixctl_conn *conn, int argc,
|
|||||||
|
|
||||||
if (cmap_count(&dp->tx_bonds) > 0) {
|
if (cmap_count(&dp->tx_bonds) > 0) {
|
||||||
struct tx_bond *dp_bond_entry;
|
struct tx_bond *dp_bond_entry;
|
||||||
uint32_t slave_id;
|
|
||||||
|
|
||||||
ds_put_cstr(&reply, "Bonds:\n");
|
ds_put_cstr(&reply, "Bonds:\n");
|
||||||
CMAP_FOR_EACH (dp_bond_entry, node, &dp->tx_bonds) {
|
CMAP_FOR_EACH (dp_bond_entry, node, &dp->tx_bonds) {
|
||||||
ds_put_format(&reply, " bond-id %"PRIu32":\n",
|
ds_put_format(&reply, " bond-id %"PRIu32":\n",
|
||||||
dp_bond_entry->bond_id);
|
dp_bond_entry->bond_id);
|
||||||
for (int bucket = 0; bucket < BOND_BUCKETS; bucket++) {
|
for (int bucket = 0; bucket < BOND_BUCKETS; bucket++) {
|
||||||
slave_id =
|
uint32_t member_id = odp_to_u32(
|
||||||
odp_to_u32(dp_bond_entry->slave_buckets[bucket].slave_id);
|
dp_bond_entry->member_buckets[bucket].member_id);
|
||||||
ds_put_format(&reply, " bucket %d - slave %"PRIu32"\n",
|
ds_put_format(&reply,
|
||||||
bucket, slave_id);
|
" bucket %d - member %"PRIu32"\n",
|
||||||
|
bucket, member_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6710,10 +6710,10 @@ dp_netdev_add_bond_tx_to_pmd(struct dp_netdev_pmd_thread *pmd,
|
|||||||
for (int i = 0; i < BOND_BUCKETS; i++) {
|
for (int i = 0; i < BOND_BUCKETS; i++) {
|
||||||
uint64_t n_packets, n_bytes;
|
uint64_t n_packets, n_bytes;
|
||||||
|
|
||||||
atomic_read_relaxed(&tx->slave_buckets[i].n_packets, &n_packets);
|
atomic_read_relaxed(&tx->member_buckets[i].n_packets, &n_packets);
|
||||||
atomic_read_relaxed(&tx->slave_buckets[i].n_bytes, &n_bytes);
|
atomic_read_relaxed(&tx->member_buckets[i].n_bytes, &n_bytes);
|
||||||
atomic_init(&new_tx->slave_buckets[i].n_packets, n_packets);
|
atomic_init(&new_tx->member_buckets[i].n_packets, n_packets);
|
||||||
atomic_init(&new_tx->slave_buckets[i].n_bytes, n_bytes);
|
atomic_init(&new_tx->member_buckets[i].n_bytes, n_bytes);
|
||||||
}
|
}
|
||||||
cmap_replace(&pmd->tx_bonds, &tx->node, &new_tx->node,
|
cmap_replace(&pmd->tx_bonds, &tx->node, &new_tx->node,
|
||||||
hash_bond_id(bond->bond_id));
|
hash_bond_id(bond->bond_id));
|
||||||
@ -7639,18 +7639,19 @@ dp_execute_lb_output_action(struct dp_netdev_pmd_thread *pmd,
|
|||||||
|
|
||||||
DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
|
DP_PACKET_BATCH_FOR_EACH (i, packet, packets_) {
|
||||||
/*
|
/*
|
||||||
* Lookup the bond-hash table using hash to get the slave.
|
* Lookup the bond-hash table using hash to get the member.
|
||||||
*/
|
*/
|
||||||
uint32_t hash = dp_packet_get_rss_hash(packet);
|
uint32_t hash = dp_packet_get_rss_hash(packet);
|
||||||
struct slave_entry *s_entry = &p_bond->slave_buckets[hash & BOND_MASK];
|
struct member_entry *s_entry
|
||||||
odp_port_t bond_member = s_entry->slave_id;
|
= &p_bond->member_buckets[hash & BOND_MASK];
|
||||||
|
odp_port_t bond_member = s_entry->member_id;
|
||||||
uint32_t size = dp_packet_size(packet);
|
uint32_t size = dp_packet_size(packet);
|
||||||
struct dp_packet_batch output_pkt;
|
struct dp_packet_batch output_pkt;
|
||||||
|
|
||||||
dp_packet_batch_init_packet(&output_pkt, packet);
|
dp_packet_batch_init_packet(&output_pkt, packet);
|
||||||
if (OVS_LIKELY(dp_execute_output_action(pmd, &output_pkt, true,
|
if (OVS_LIKELY(dp_execute_output_action(pmd, &output_pkt, true,
|
||||||
bond_member))) {
|
bond_member))) {
|
||||||
/* Update slave stats. */
|
/* Update member stats. */
|
||||||
non_atomic_ullong_add(&s_entry->n_packets, 1);
|
non_atomic_ullong_add(&s_entry->n_packets, 1);
|
||||||
non_atomic_ullong_add(&s_entry->n_bytes, size);
|
non_atomic_ullong_add(&s_entry->n_bytes, size);
|
||||||
}
|
}
|
||||||
@ -8293,7 +8294,7 @@ dpif_netdev_ipf_dump_done(struct dpif *dpif OVS_UNUSED, void *ipf_dump_ctx)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
dpif_netdev_bond_add(struct dpif *dpif, uint32_t bond_id,
|
dpif_netdev_bond_add(struct dpif *dpif, uint32_t bond_id,
|
||||||
odp_port_t *slave_map)
|
odp_port_t *member_map)
|
||||||
{
|
{
|
||||||
struct tx_bond *new_tx = xzalloc(sizeof *new_tx);
|
struct tx_bond *new_tx = xzalloc(sizeof *new_tx);
|
||||||
struct dp_netdev *dp = get_dp_netdev(dpif);
|
struct dp_netdev *dp = get_dp_netdev(dpif);
|
||||||
@ -8302,7 +8303,7 @@ dpif_netdev_bond_add(struct dpif *dpif, uint32_t bond_id,
|
|||||||
/* Prepare new bond mapping. */
|
/* Prepare new bond mapping. */
|
||||||
new_tx->bond_id = bond_id;
|
new_tx->bond_id = bond_id;
|
||||||
for (int bucket = 0; bucket < BOND_BUCKETS; bucket++) {
|
for (int bucket = 0; bucket < BOND_BUCKETS; bucket++) {
|
||||||
new_tx->slave_buckets[bucket].slave_id = slave_map[bucket];
|
new_tx->member_buckets[bucket].member_id = member_map[bucket];
|
||||||
}
|
}
|
||||||
|
|
||||||
ovs_mutex_lock(&dp->bond_mutex);
|
ovs_mutex_lock(&dp->bond_mutex);
|
||||||
@ -8375,7 +8376,7 @@ dpif_netdev_bond_stats_get(struct dpif *dpif, uint32_t bond_id,
|
|||||||
for (int i = 0; i < BOND_BUCKETS; i++) {
|
for (int i = 0; i < BOND_BUCKETS; i++) {
|
||||||
uint64_t pmd_n_bytes;
|
uint64_t pmd_n_bytes;
|
||||||
|
|
||||||
atomic_read_relaxed(&pmd_bond_entry->slave_buckets[i].n_bytes,
|
atomic_read_relaxed(&pmd_bond_entry->member_buckets[i].n_bytes,
|
||||||
&pmd_n_bytes);
|
&pmd_n_bytes);
|
||||||
n_bytes[i] += pmd_n_bytes;
|
n_bytes[i] += pmd_n_bytes;
|
||||||
}
|
}
|
||||||
|
@ -617,9 +617,9 @@ struct dpif_class {
|
|||||||
int (*meter_del)(struct dpif *, ofproto_meter_id meter_id,
|
int (*meter_del)(struct dpif *, ofproto_meter_id meter_id,
|
||||||
struct ofputil_meter_stats *, uint16_t n_bands);
|
struct ofputil_meter_stats *, uint16_t n_bands);
|
||||||
|
|
||||||
/* Adds a bond with 'bond_id' and the slave-map to 'dpif'. */
|
/* Adds a bond with 'bond_id' and the member-map to 'dpif'. */
|
||||||
int (*bond_add)(struct dpif *dpif, uint32_t bond_id,
|
int (*bond_add)(struct dpif *dpif, uint32_t bond_id,
|
||||||
odp_port_t *slave_map);
|
odp_port_t *member_map);
|
||||||
|
|
||||||
/* Removes bond identified by 'bond_id' from 'dpif'. */
|
/* Removes bond identified by 'bond_id' from 'dpif'. */
|
||||||
int (*bond_del)(struct dpif *dpif, uint32_t bond_id);
|
int (*bond_del)(struct dpif *dpif, uint32_t bond_id);
|
||||||
|
@ -1993,10 +1993,10 @@ dpif_meter_del(struct dpif *dpif, ofproto_meter_id meter_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dpif_bond_add(struct dpif *dpif, uint32_t bond_id, odp_port_t *slave_map)
|
dpif_bond_add(struct dpif *dpif, uint32_t bond_id, odp_port_t *member_map)
|
||||||
{
|
{
|
||||||
return dpif->dpif_class->bond_del
|
return dpif->dpif_class->bond_del
|
||||||
? dpif->dpif_class->bond_add(dpif, bond_id, slave_map)
|
? dpif->dpif_class->bond_add(dpif, bond_id, member_map)
|
||||||
: EOPNOTSUPP;
|
: EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,7 +898,7 @@ int dpif_meter_del(struct dpif *, ofproto_meter_id meter_id,
|
|||||||
#define BOND_MASK 0xff
|
#define BOND_MASK 0xff
|
||||||
#define BOND_BUCKETS (BOND_MASK + 1)
|
#define BOND_BUCKETS (BOND_MASK + 1)
|
||||||
|
|
||||||
int dpif_bond_add(struct dpif *, uint32_t bond_id, odp_port_t *slave_map);
|
int dpif_bond_add(struct dpif *, uint32_t bond_id, odp_port_t *member_map);
|
||||||
int dpif_bond_del(struct dpif *, uint32_t bond_id);
|
int dpif_bond_del(struct dpif *, uint32_t bond_id);
|
||||||
int dpif_bond_stats_get(struct dpif *, uint32_t bond_id, uint64_t *n_bytes);
|
int dpif_bond_stats_get(struct dpif *, uint32_t bond_id, uint64_t *n_bytes);
|
||||||
bool dpif_supports_lb_output_action(const struct dpif *);
|
bool dpif_supports_lb_output_action(const struct dpif *);
|
||||||
|
539
lib/lacp.c
539
lib/lacp.c
@ -92,12 +92,13 @@ enum pdu_subtype {
|
|||||||
SUBTYPE_MARKER, /* Link Aggregation Marker Protocol. */
|
SUBTYPE_MARKER, /* Link Aggregation Marker Protocol. */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum slave_status {
|
enum member_status {
|
||||||
LACP_CURRENT, /* Current State. Partner up to date. */
|
LACP_CURRENT, /* Current State. Partner up to date. */
|
||||||
LACP_EXPIRED, /* Expired State. Partner out of date. */
|
LACP_EXPIRED, /* Expired State. Partner out of date. */
|
||||||
LACP_DEFAULTED, /* Defaulted State. No partner. */
|
LACP_DEFAULTED, /* Defaulted State. No partner. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A LACP primary interface. */
|
||||||
struct lacp {
|
struct lacp {
|
||||||
struct ovs_list node; /* Node in all_lacps list. */
|
struct ovs_list node; /* Node in all_lacps list. */
|
||||||
char *name; /* Name of this lacp object. */
|
char *name; /* Name of this lacp object. */
|
||||||
@ -105,8 +106,8 @@ struct lacp {
|
|||||||
uint16_t sys_priority; /* System Priority. */
|
uint16_t sys_priority; /* System Priority. */
|
||||||
bool active; /* Active or Passive. */
|
bool active; /* Active or Passive. */
|
||||||
|
|
||||||
struct hmap slaves; /* Slaves this LACP object controls. */
|
struct hmap members; /* Members this LACP object controls. */
|
||||||
struct slave *key_slave; /* Slave whose ID will be the aggregation key. */
|
struct member *key_member; /* Member whose ID will be aggregation key. */
|
||||||
|
|
||||||
bool fast; /* True if using fast probe interval. */
|
bool fast; /* True if using fast probe interval. */
|
||||||
bool negotiated; /* True if LACP negotiations were successful. */
|
bool negotiated; /* True if LACP negotiations were successful. */
|
||||||
@ -116,17 +117,18 @@ struct lacp {
|
|||||||
struct ovs_refcount ref_cnt;
|
struct ovs_refcount ref_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct slave {
|
/* A LACP member interface. */
|
||||||
void *aux; /* Handle used to identify this slave. */
|
struct member {
|
||||||
struct hmap_node node; /* Node in master's slaves map. */
|
void *aux; /* Handle used to identify this member. */
|
||||||
|
struct hmap_node node; /* Node in primary's members map. */
|
||||||
|
|
||||||
struct lacp *lacp; /* LACP object containing this slave. */
|
struct lacp *lacp; /* LACP object containing this member. */
|
||||||
uint16_t port_id; /* Port ID. */
|
uint16_t port_id; /* Port ID. */
|
||||||
uint16_t port_priority; /* Port Priority. */
|
uint16_t port_priority; /* Port Priority. */
|
||||||
uint16_t key; /* Aggregation Key. 0 if default. */
|
uint16_t key; /* Aggregation Key. 0 if default. */
|
||||||
char *name; /* Name of this slave. */
|
char *name; /* Name of this member. */
|
||||||
|
|
||||||
enum slave_status status; /* Slave status. */
|
enum member_status status; /* Member status. */
|
||||||
bool attached; /* Attached. Traffic may flow. */
|
bool attached; /* Attached. Traffic may flow. */
|
||||||
bool carrier_up; /* Carrier state of link. */
|
bool carrier_up; /* Carrier state of link. */
|
||||||
struct lacp_info partner; /* Partner information. */
|
struct lacp_info partner; /* Partner information. */
|
||||||
@ -149,20 +151,20 @@ static struct ovs_list *const all_lacps OVS_GUARDED_BY(mutex) = &all_lacps__;
|
|||||||
|
|
||||||
static void lacp_update_attached(struct lacp *) OVS_REQUIRES(mutex);
|
static void lacp_update_attached(struct lacp *) OVS_REQUIRES(mutex);
|
||||||
|
|
||||||
static void slave_destroy(struct slave *) OVS_REQUIRES(mutex);
|
static void member_destroy(struct member *) OVS_REQUIRES(mutex);
|
||||||
static void slave_set_defaulted(struct slave *) OVS_REQUIRES(mutex);
|
static void member_set_defaulted(struct member *) OVS_REQUIRES(mutex);
|
||||||
static void slave_set_expired(struct slave *) OVS_REQUIRES(mutex);
|
static void member_set_expired(struct member *) OVS_REQUIRES(mutex);
|
||||||
static void slave_get_actor(struct slave *, struct lacp_info *actor)
|
static void member_get_actor(struct member *, struct lacp_info *actor)
|
||||||
OVS_REQUIRES(mutex);
|
OVS_REQUIRES(mutex);
|
||||||
static void slave_get_priority(struct slave *, struct lacp_info *priority)
|
static void member_get_priority(struct member *, struct lacp_info *priority)
|
||||||
OVS_REQUIRES(mutex);
|
OVS_REQUIRES(mutex);
|
||||||
static bool slave_may_tx(const struct slave *)
|
static bool member_may_tx(const struct member *)
|
||||||
OVS_REQUIRES(mutex);
|
OVS_REQUIRES(mutex);
|
||||||
static struct slave *slave_lookup(const struct lacp *, const void *slave)
|
static struct member *member_lookup(const struct lacp *, const void *member)
|
||||||
OVS_REQUIRES(mutex);
|
OVS_REQUIRES(mutex);
|
||||||
static bool info_tx_equal(struct lacp_info *, struct lacp_info *)
|
static bool info_tx_equal(struct lacp_info *, struct lacp_info *)
|
||||||
OVS_REQUIRES(mutex);
|
OVS_REQUIRES(mutex);
|
||||||
static bool slave_may_enable__(struct slave *slave) OVS_REQUIRES(mutex);
|
static bool member_may_enable__(struct member *) OVS_REQUIRES(mutex);
|
||||||
|
|
||||||
static unixctl_cb_func lacp_unixctl_show;
|
static unixctl_cb_func lacp_unixctl_show;
|
||||||
static unixctl_cb_func lacp_unixctl_show_stats;
|
static unixctl_cb_func lacp_unixctl_show_stats;
|
||||||
@ -254,7 +256,7 @@ lacp_create(void) OVS_EXCLUDED(mutex)
|
|||||||
struct lacp *lacp;
|
struct lacp *lacp;
|
||||||
|
|
||||||
lacp = xzalloc(sizeof *lacp);
|
lacp = xzalloc(sizeof *lacp);
|
||||||
hmap_init(&lacp->slaves);
|
hmap_init(&lacp->members);
|
||||||
ovs_refcount_init(&lacp->ref_cnt);
|
ovs_refcount_init(&lacp->ref_cnt);
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
@ -273,19 +275,19 @@ lacp_ref(const struct lacp *lacp_)
|
|||||||
return lacp;
|
return lacp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroys 'lacp' and its slaves. Does nothing if 'lacp' is NULL. */
|
/* Destroys 'lacp' and its members. Does nothing if 'lacp' is NULL. */
|
||||||
void
|
void
|
||||||
lacp_unref(struct lacp *lacp) OVS_EXCLUDED(mutex)
|
lacp_unref(struct lacp *lacp) OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
if (lacp && ovs_refcount_unref_relaxed(&lacp->ref_cnt) == 1) {
|
if (lacp && ovs_refcount_unref_relaxed(&lacp->ref_cnt) == 1) {
|
||||||
struct slave *slave, *next;
|
struct member *member, *next;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
HMAP_FOR_EACH_SAFE (slave, next, node, &lacp->slaves) {
|
HMAP_FOR_EACH_SAFE (member, next, node, &lacp->members) {
|
||||||
slave_destroy(slave);
|
member_destroy(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
hmap_destroy(&lacp->slaves);
|
hmap_destroy(&lacp->members);
|
||||||
ovs_list_remove(&lacp->node);
|
ovs_list_remove(&lacp->node);
|
||||||
free(lacp->name);
|
free(lacp->name);
|
||||||
free(lacp);
|
free(lacp);
|
||||||
@ -336,39 +338,40 @@ lacp_is_active(const struct lacp *lacp) OVS_EXCLUDED(mutex)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Processes 'packet' which was received on 'slave_'. This function should be
|
/* Processes 'packet' which was received on 'member_'. This function should be
|
||||||
* called on all packets received on 'slave_' with Ethernet Type ETH_TYPE_LACP.
|
* called on all packets received on 'member_' with Ethernet Type
|
||||||
|
* ETH_TYPE_LACP.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
lacp_process_packet(struct lacp *lacp, const void *slave_,
|
lacp_process_packet(struct lacp *lacp, const void *member_,
|
||||||
const struct dp_packet *packet)
|
const struct dp_packet *packet)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
|
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
|
||||||
const struct lacp_pdu *pdu;
|
const struct lacp_pdu *pdu;
|
||||||
long long int tx_rate;
|
long long int tx_rate;
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
bool lacp_may_enable = false;
|
bool lacp_may_enable = false;
|
||||||
enum pdu_subtype subtype;
|
enum pdu_subtype subtype;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
if (!slave) {
|
if (!member) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
slave->count_rx_pdus++;
|
member->count_rx_pdus++;
|
||||||
|
|
||||||
pdu = parse_lacp_packet(packet, &subtype);
|
pdu = parse_lacp_packet(packet, &subtype);
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case SUBTYPE_LACP:
|
case SUBTYPE_LACP:
|
||||||
break;
|
break;
|
||||||
case SUBTYPE_MARKER:
|
case SUBTYPE_MARKER:
|
||||||
slave->count_rx_pdus_marker++;
|
member->count_rx_pdus_marker++;
|
||||||
VLOG_DBG("%s: received a LACP marker PDU.", lacp->name);
|
VLOG_DBG("%s: received a LACP marker PDU.", lacp->name);
|
||||||
goto out;
|
goto out;
|
||||||
case SUBTYPE_UNUSED:
|
case SUBTYPE_UNUSED:
|
||||||
default:
|
default:
|
||||||
slave->count_rx_pdus_bad++;
|
member->count_rx_pdus_bad++;
|
||||||
VLOG_WARN_RL(&rl, "%s: received an unparsable LACP PDU.",
|
VLOG_WARN_RL(&rl, "%s: received an unparsable LACP PDU.",
|
||||||
lacp->name);
|
lacp->name);
|
||||||
goto out;
|
goto out;
|
||||||
@ -377,30 +380,30 @@ lacp_process_packet(struct lacp *lacp, const void *slave_,
|
|||||||
/* On some NICs L1 state reporting is slow. In case LACP packets are
|
/* On some NICs L1 state reporting is slow. In case LACP packets are
|
||||||
* received while carrier (L1) state is still down, drop the LACP PDU and
|
* received while carrier (L1) state is still down, drop the LACP PDU and
|
||||||
* trigger re-checking of L1 state. */
|
* trigger re-checking of L1 state. */
|
||||||
if (!slave->carrier_up) {
|
if (!member->carrier_up) {
|
||||||
VLOG_INFO_RL(&rl, "%s: carrier state is DOWN,"
|
VLOG_INFO_RL(&rl, "%s: carrier state is DOWN,"
|
||||||
" dropping received LACP PDU.", slave->name);
|
" dropping received LACP PDU.", member->name);
|
||||||
seq_change(connectivity_seq_get());
|
seq_change(connectivity_seq_get());
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
slave->status = LACP_CURRENT;
|
member->status = LACP_CURRENT;
|
||||||
tx_rate = lacp->fast ? LACP_FAST_TIME_TX : LACP_SLOW_TIME_TX;
|
tx_rate = lacp->fast ? LACP_FAST_TIME_TX : LACP_SLOW_TIME_TX;
|
||||||
timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER * tx_rate);
|
timer_set_duration(&member->rx, LACP_RX_MULTIPLIER * tx_rate);
|
||||||
|
|
||||||
slave->ntt_actor = pdu->partner;
|
member->ntt_actor = pdu->partner;
|
||||||
|
|
||||||
/* Update our information about our partner if it's out of date. This may
|
/* Update our information about our partner if it's out of date. This may
|
||||||
* cause priorities to change so re-calculate attached status of all
|
* cause priorities to change so re-calculate attached status of all
|
||||||
* slaves. */
|
* members. */
|
||||||
if (memcmp(&slave->partner, &pdu->actor, sizeof pdu->actor)) {
|
if (memcmp(&member->partner, &pdu->actor, sizeof pdu->actor)) {
|
||||||
lacp->update = true;
|
lacp->update = true;
|
||||||
slave->partner = pdu->actor;
|
member->partner = pdu->actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate may_enable here to avoid dropping of packets till main thread
|
/* Evaluate may_enable here to avoid dropping of packets till main thread
|
||||||
* sets may_enable to true. */
|
* sets may_enable to true. */
|
||||||
lacp_may_enable = slave_may_enable__(slave);
|
lacp_may_enable = member_may_enable__(member);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
@ -426,92 +429,92 @@ lacp_status(const struct lacp *lacp) OVS_EXCLUDED(mutex)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Registers 'slave_' as subordinate to 'lacp'. This should be called at least
|
/* Registers 'member_' as subordinate to 'lacp'. This should be called at
|
||||||
* once per slave in a LACP managed bond. Should also be called whenever a
|
* least once per member in a LACP managed bond. Should also be called
|
||||||
* slave's settings change. */
|
* whenever a member's settings change. */
|
||||||
void
|
void
|
||||||
lacp_slave_register(struct lacp *lacp, void *slave_,
|
lacp_member_register(struct lacp *lacp, void *member_,
|
||||||
const struct lacp_slave_settings *s)
|
const struct lacp_member_settings *s)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
if (!slave) {
|
if (!member) {
|
||||||
slave = xzalloc(sizeof *slave);
|
member = xzalloc(sizeof *member);
|
||||||
slave->lacp = lacp;
|
member->lacp = lacp;
|
||||||
slave->aux = slave_;
|
member->aux = member_;
|
||||||
hmap_insert(&lacp->slaves, &slave->node, hash_pointer(slave_, 0));
|
hmap_insert(&lacp->members, &member->node, hash_pointer(member_, 0));
|
||||||
slave_set_defaulted(slave);
|
member_set_defaulted(member);
|
||||||
|
|
||||||
if (!lacp->key_slave) {
|
if (!lacp->key_member) {
|
||||||
lacp->key_slave = slave;
|
lacp->key_member = member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!slave->name || strcmp(s->name, slave->name)) {
|
if (!member->name || strcmp(s->name, member->name)) {
|
||||||
free(slave->name);
|
free(member->name);
|
||||||
slave->name = xstrdup(s->name);
|
member->name = xstrdup(s->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->port_id != s->id
|
if (member->port_id != s->id
|
||||||
|| slave->port_priority != s->priority
|
|| member->port_priority != s->priority
|
||||||
|| slave->key != s->key) {
|
|| member->key != s->key) {
|
||||||
slave->port_id = s->id;
|
member->port_id = s->id;
|
||||||
slave->port_priority = s->priority;
|
member->port_priority = s->priority;
|
||||||
slave->key = s->key;
|
member->key = s->key;
|
||||||
|
|
||||||
lacp->update = true;
|
lacp->update = true;
|
||||||
|
|
||||||
if (lacp->active || lacp->negotiated) {
|
if (lacp->active || lacp->negotiated) {
|
||||||
slave_set_expired(slave);
|
member_set_expired(member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unregisters 'slave_' with 'lacp'. */
|
/* Unregisters 'member_' with 'lacp'. */
|
||||||
void
|
void
|
||||||
lacp_slave_unregister(struct lacp *lacp, const void *slave_)
|
lacp_member_unregister(struct lacp *lacp, const void *member_)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
if (slave) {
|
if (member) {
|
||||||
slave_destroy(slave);
|
member_destroy(member);
|
||||||
lacp->update = true;
|
lacp->update = true;
|
||||||
}
|
}
|
||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function should be called whenever the carrier status of 'slave_' has
|
/* This function should be called whenever the carrier status of 'member_' has
|
||||||
* changed. If 'lacp' is null, this function has no effect.*/
|
* changed. If 'lacp' is null, this function has no effect.*/
|
||||||
void
|
void
|
||||||
lacp_slave_carrier_changed(const struct lacp *lacp, const void *slave_,
|
lacp_member_carrier_changed(const struct lacp *lacp, const void *member_,
|
||||||
bool carrier_up)
|
bool carrier_up)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
if (!lacp) {
|
if (!lacp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
if (!slave) {
|
if (!member) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->status == LACP_CURRENT || slave->lacp->active) {
|
if (member->status == LACP_CURRENT || member->lacp->active) {
|
||||||
slave_set_expired(slave);
|
member_set_expired(member);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->carrier_up != carrier_up) {
|
if (member->carrier_up != carrier_up) {
|
||||||
slave->carrier_up = carrier_up;
|
member->carrier_up = carrier_up;
|
||||||
slave->count_carrier_changed++;
|
member->count_carrier_changed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -519,35 +522,35 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
slave_may_enable__(struct slave *slave) OVS_REQUIRES(mutex)
|
member_may_enable__(struct member *member) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
/* The slave may be enabled if it's attached to an aggregator and its
|
/* The member may be enabled if it's attached to an aggregator and its
|
||||||
* partner is synchronized.*/
|
* partner is synchronized.*/
|
||||||
return slave->attached && (slave->partner.state & LACP_STATE_SYNC
|
return member->attached && (member->partner.state & LACP_STATE_SYNC
|
||||||
|| (slave->lacp && slave->lacp->fallback_ab
|
|| (member->lacp && member->lacp->fallback_ab
|
||||||
&& slave->status == LACP_DEFAULTED));
|
&& member->status == LACP_DEFAULTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function should be called before enabling 'slave_' to send or receive
|
/* This function should be called before enabling 'member_' to send or receive
|
||||||
* traffic. If it returns false, 'slave_' should not enabled. As a
|
* traffic. If it returns false, 'member_' should not enabled. As a
|
||||||
* convenience, returns true if 'lacp' is NULL. */
|
* convenience, returns true if 'lacp' is NULL. */
|
||||||
bool
|
bool
|
||||||
lacp_slave_may_enable(const struct lacp *lacp, const void *slave_)
|
lacp_member_may_enable(const struct lacp *lacp, const void *member_)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
if (lacp) {
|
if (lacp) {
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
if (slave) {
|
if (member) {
|
||||||
/* It is only called when carrier is up. So, enable slave's
|
/* It is only called when carrier is up. So, enable member's
|
||||||
* carrier state if it is currently down. */
|
* carrier state if it is currently down. */
|
||||||
if (!slave->carrier_up) {
|
if (!member->carrier_up) {
|
||||||
slave->carrier_up = true;
|
member->carrier_up = true;
|
||||||
}
|
}
|
||||||
ret = slave_may_enable__(slave);
|
ret = member_may_enable__(member);
|
||||||
}
|
}
|
||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
@ -556,19 +559,19 @@ lacp_slave_may_enable(const struct lacp *lacp, const void *slave_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if partner information on 'slave_' is up to date. 'slave_'
|
/* Returns true if partner information on 'member_' is up to date. 'member_'
|
||||||
* not being current, generally indicates a connectivity problem, or a
|
* not being current, generally indicates a connectivity problem, or a
|
||||||
* misconfigured (or broken) partner. */
|
* misconfigured (or broken) partner. */
|
||||||
bool
|
bool
|
||||||
lacp_slave_is_current(const struct lacp *lacp, const void *slave_)
|
lacp_member_is_current(const struct lacp *lacp, const void *member_)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
ret = slave ? slave->status != LACP_DEFAULTED : false;
|
ret = member ? member->status != LACP_DEFAULTED : false;
|
||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -577,21 +580,21 @@ lacp_slave_is_current(const struct lacp *lacp, const void *slave_)
|
|||||||
void
|
void
|
||||||
lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
|
lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
if (timer_expired(&slave->rx)) {
|
if (timer_expired(&member->rx)) {
|
||||||
enum slave_status old_status = slave->status;
|
enum member_status old_status = member->status;
|
||||||
|
|
||||||
if (slave->status == LACP_CURRENT) {
|
if (member->status == LACP_CURRENT) {
|
||||||
slave_set_expired(slave);
|
member_set_expired(member);
|
||||||
slave->count_link_expired++;
|
member->count_link_expired++;
|
||||||
} else if (slave->status == LACP_EXPIRED) {
|
} else if (member->status == LACP_EXPIRED) {
|
||||||
slave_set_defaulted(slave);
|
member_set_defaulted(member);
|
||||||
slave->count_link_defaulted++;
|
member->count_link_defaulted++;
|
||||||
}
|
}
|
||||||
if (slave->status != old_status) {
|
if (member->status != old_status) {
|
||||||
seq_change(connectivity_seq_get());
|
seq_change(connectivity_seq_get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -602,30 +605,30 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
|
|||||||
seq_change(connectivity_seq_get());
|
seq_change(connectivity_seq_get());
|
||||||
}
|
}
|
||||||
|
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
struct lacp_info actor;
|
struct lacp_info actor;
|
||||||
|
|
||||||
if (!slave_may_tx(slave)) {
|
if (!member_may_tx(member)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
slave_get_actor(slave, &actor);
|
member_get_actor(member, &actor);
|
||||||
|
|
||||||
if (timer_expired(&slave->tx)
|
if (timer_expired(&member->tx)
|
||||||
|| !info_tx_equal(&actor, &slave->ntt_actor)) {
|
|| !info_tx_equal(&actor, &member->ntt_actor)) {
|
||||||
long long int duration;
|
long long int duration;
|
||||||
struct lacp_pdu pdu;
|
struct lacp_pdu pdu;
|
||||||
|
|
||||||
slave->ntt_actor = actor;
|
member->ntt_actor = actor;
|
||||||
compose_lacp_pdu(&actor, &slave->partner, &pdu);
|
compose_lacp_pdu(&actor, &member->partner, &pdu);
|
||||||
send_pdu(slave->aux, &pdu, sizeof pdu);
|
send_pdu(member->aux, &pdu, sizeof pdu);
|
||||||
slave->count_tx_pdus++;
|
member->count_tx_pdus++;
|
||||||
|
|
||||||
duration = (slave->partner.state & LACP_STATE_TIME
|
duration = (member->partner.state & LACP_STATE_TIME
|
||||||
? LACP_FAST_TIME_TX
|
? LACP_FAST_TIME_TX
|
||||||
: LACP_SLOW_TIME_TX);
|
: LACP_SLOW_TIME_TX);
|
||||||
|
|
||||||
timer_set_duration(&slave->tx, duration);
|
timer_set_duration(&member->tx, duration);
|
||||||
seq_change(connectivity_seq_get());
|
seq_change(connectivity_seq_get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -636,16 +639,16 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
|
|||||||
void
|
void
|
||||||
lacp_wait(struct lacp *lacp) OVS_EXCLUDED(mutex)
|
lacp_wait(struct lacp *lacp) OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
|
|
||||||
lacp_lock();
|
lacp_lock();
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
if (slave_may_tx(slave)) {
|
if (member_may_tx(member)) {
|
||||||
timer_wait(&slave->tx);
|
timer_wait(&member->tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->status != LACP_DEFAULTED) {
|
if (member->status != LACP_DEFAULTED) {
|
||||||
timer_wait(&slave->rx);
|
timer_wait(&member->rx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
@ -653,12 +656,12 @@ lacp_wait(struct lacp *lacp) OVS_EXCLUDED(mutex)
|
|||||||
|
|
||||||
/* Static Helpers. */
|
/* Static Helpers. */
|
||||||
|
|
||||||
/* Updates the attached status of all slaves controlled by 'lacp' and sets its
|
/* Updates the attached status of all members controlled by 'lacp' and sets its
|
||||||
* negotiated parameter to true if any slaves are attachable. */
|
* negotiated parameter to true if any members are attachable. */
|
||||||
static void
|
static void
|
||||||
lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
|
lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
struct slave *lead, *lead_current, *slave;
|
struct member *lead, *lead_current, *member;
|
||||||
struct lacp_info lead_pri;
|
struct lacp_info lead_pri;
|
||||||
bool lead_enable;
|
bool lead_enable;
|
||||||
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
|
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 10);
|
||||||
@ -671,12 +674,12 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
|
|
||||||
/* Check if there is a working interface.
|
/* Check if there is a working interface.
|
||||||
* Store as lead_current, if there is one. */
|
* Store as lead_current, if there is one. */
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
if (slave->status == LACP_CURRENT && slave->attached) {
|
if (member->status == LACP_CURRENT && member->attached) {
|
||||||
struct lacp_info pri;
|
struct lacp_info pri;
|
||||||
slave_get_priority(slave, &pri);
|
member_get_priority(member, &pri);
|
||||||
if (!lead_current || memcmp(&pri, &lead_pri, sizeof pri) < 0) {
|
if (!lead_current || memcmp(&pri, &lead_pri, sizeof pri) < 0) {
|
||||||
lead_current = slave;
|
lead_current = member;
|
||||||
lead = lead_current;
|
lead = lead_current;
|
||||||
lead_pri = pri;
|
lead_pri = pri;
|
||||||
lead_enable = true;
|
lead_enable = true;
|
||||||
@ -685,43 +688,43 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Find interface with highest priority. */
|
/* Find interface with highest priority. */
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
struct lacp_info pri;
|
struct lacp_info pri;
|
||||||
|
|
||||||
slave->attached = false;
|
member->attached = false;
|
||||||
|
|
||||||
/* XXX: In the future allow users to configure the expected system ID.
|
/* XXX: In the future allow users to configure the expected system ID.
|
||||||
* For now just special case loopback. */
|
* For now just special case loopback. */
|
||||||
if (eth_addr_equals(slave->partner.sys_id, slave->lacp->sys_id)) {
|
if (eth_addr_equals(member->partner.sys_id, member->lacp->sys_id)) {
|
||||||
VLOG_WARN_RL(&rl, "slave %s: Loopback detected. Slave is "
|
VLOG_WARN_RL(&rl, "member %s: Loopback detected. Interface is "
|
||||||
"connected to its own bond", slave->name);
|
"connected to its own bond", member->name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->status == LACP_DEFAULTED) {
|
if (member->status == LACP_DEFAULTED) {
|
||||||
if (lacp->fallback_ab) {
|
if (lacp->fallback_ab) {
|
||||||
slave->attached = true;
|
member->attached = true;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
slave_get_priority(slave, &pri);
|
member_get_priority(member, &pri);
|
||||||
bool enable = slave_may_enable__(slave);
|
bool enable = member_may_enable__(member);
|
||||||
|
|
||||||
/* Check if partner MAC address is the same as on the working
|
/* Check if partner MAC address is the same as on the working
|
||||||
* interface. Activate slave only if the MAC is the same, or
|
* interface. Activate member only if the MAC is the same, or
|
||||||
* there is no working interface. */
|
* there is no working interface. */
|
||||||
if (!lead_current || (lead_current
|
if (!lead_current || (lead_current
|
||||||
&& eth_addr_equals(slave->partner.sys_id,
|
&& eth_addr_equals(member->partner.sys_id,
|
||||||
lead_current->partner.sys_id))) {
|
lead_current->partner.sys_id))) {
|
||||||
slave->attached = true;
|
member->attached = true;
|
||||||
}
|
}
|
||||||
if (slave->attached &&
|
if (member->attached &&
|
||||||
(!lead
|
(!lead
|
||||||
|| enable > lead_enable
|
|| enable > lead_enable
|
||||||
|| (enable == lead_enable
|
|| (enable == lead_enable
|
||||||
&& memcmp(&pri, &lead_pri, sizeof pri) < 0))) {
|
&& memcmp(&pri, &lead_pri, sizeof pri) < 0))) {
|
||||||
lead = slave;
|
lead = member;
|
||||||
lead_enable = enable;
|
lead_enable = enable;
|
||||||
lead_pri = pri;
|
lead_pri = pri;
|
||||||
}
|
}
|
||||||
@ -730,65 +733,66 @@ lacp_update_attached(struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
lacp->negotiated = lead != NULL;
|
lacp->negotiated = lead != NULL;
|
||||||
|
|
||||||
if (lead) {
|
if (lead) {
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
if ((lacp->fallback_ab && slave->status == LACP_DEFAULTED)
|
if ((lacp->fallback_ab && member->status == LACP_DEFAULTED)
|
||||||
|| lead->partner.key != slave->partner.key
|
|| lead->partner.key != member->partner.key
|
||||||
|| !eth_addr_equals(lead->partner.sys_id,
|
|| !eth_addr_equals(lead->partner.sys_id,
|
||||||
slave->partner.sys_id)) {
|
member->partner.sys_id)) {
|
||||||
slave->attached = false;
|
member->attached = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slave_destroy(struct slave *slave) OVS_REQUIRES(mutex)
|
member_destroy(struct member *member) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
if (slave) {
|
if (member) {
|
||||||
struct lacp *lacp = slave->lacp;
|
struct lacp *lacp = member->lacp;
|
||||||
|
|
||||||
lacp->update = true;
|
lacp->update = true;
|
||||||
hmap_remove(&lacp->slaves, &slave->node);
|
hmap_remove(&lacp->members, &member->node);
|
||||||
|
|
||||||
if (lacp->key_slave == slave) {
|
if (lacp->key_member == member) {
|
||||||
struct hmap_node *slave_node = hmap_first(&lacp->slaves);
|
struct hmap_node *member_node = hmap_first(&lacp->members);
|
||||||
|
|
||||||
if (slave_node) {
|
if (member_node) {
|
||||||
lacp->key_slave = CONTAINER_OF(slave_node, struct slave, node);
|
lacp->key_member = CONTAINER_OF(member_node, struct member,
|
||||||
|
node);
|
||||||
} else {
|
} else {
|
||||||
lacp->key_slave = NULL;
|
lacp->key_member = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(slave->name);
|
free(member->name);
|
||||||
free(slave);
|
free(member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slave_set_defaulted(struct slave *slave) OVS_REQUIRES(mutex)
|
member_set_defaulted(struct member *member) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
memset(&slave->partner, 0, sizeof slave->partner);
|
memset(&member->partner, 0, sizeof member->partner);
|
||||||
|
|
||||||
slave->lacp->update = true;
|
member->lacp->update = true;
|
||||||
slave->status = LACP_DEFAULTED;
|
member->status = LACP_DEFAULTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slave_set_expired(struct slave *slave) OVS_REQUIRES(mutex)
|
member_set_expired(struct member *member) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
slave->status = LACP_EXPIRED;
|
member->status = LACP_EXPIRED;
|
||||||
slave->partner.state |= LACP_STATE_TIME;
|
member->partner.state |= LACP_STATE_TIME;
|
||||||
slave->partner.state &= ~LACP_STATE_SYNC;
|
member->partner.state &= ~LACP_STATE_SYNC;
|
||||||
|
|
||||||
timer_set_duration(&slave->rx, LACP_RX_MULTIPLIER * LACP_FAST_TIME_TX);
|
timer_set_duration(&member->rx, LACP_RX_MULTIPLIER * LACP_FAST_TIME_TX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
slave_get_actor(struct slave *slave, struct lacp_info *actor)
|
member_get_actor(struct member *member, struct lacp_info *actor)
|
||||||
OVS_REQUIRES(mutex)
|
OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
struct lacp *lacp = slave->lacp;
|
struct lacp *lacp = member->lacp;
|
||||||
uint16_t key;
|
uint16_t key;
|
||||||
uint8_t state = 0;
|
uint8_t state = 0;
|
||||||
|
|
||||||
@ -800,62 +804,62 @@ slave_get_actor(struct slave *slave, struct lacp_info *actor)
|
|||||||
state |= LACP_STATE_TIME;
|
state |= LACP_STATE_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->attached) {
|
if (member->attached) {
|
||||||
state |= LACP_STATE_SYNC;
|
state |= LACP_STATE_SYNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->status == LACP_DEFAULTED) {
|
if (member->status == LACP_DEFAULTED) {
|
||||||
state |= LACP_STATE_DEF;
|
state |= LACP_STATE_DEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->status == LACP_EXPIRED) {
|
if (member->status == LACP_EXPIRED) {
|
||||||
state |= LACP_STATE_EXP;
|
state |= LACP_STATE_EXP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hmap_count(&lacp->slaves) > 1) {
|
if (hmap_count(&lacp->members) > 1) {
|
||||||
state |= LACP_STATE_AGG;
|
state |= LACP_STATE_AGG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slave->attached || !lacp->negotiated) {
|
if (member->attached || !lacp->negotiated) {
|
||||||
state |= LACP_STATE_COL | LACP_STATE_DIST;
|
state |= LACP_STATE_COL | LACP_STATE_DIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
key = lacp->key_slave->key;
|
key = lacp->key_member->key;
|
||||||
if (!key) {
|
if (!key) {
|
||||||
key = lacp->key_slave->port_id;
|
key = lacp->key_member->port_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
actor->state = state;
|
actor->state = state;
|
||||||
actor->key = htons(key);
|
actor->key = htons(key);
|
||||||
actor->port_priority = htons(slave->port_priority);
|
actor->port_priority = htons(member->port_priority);
|
||||||
actor->port_id = htons(slave->port_id);
|
actor->port_id = htons(member->port_id);
|
||||||
actor->sys_priority = htons(lacp->sys_priority);
|
actor->sys_priority = htons(lacp->sys_priority);
|
||||||
actor->sys_id = lacp->sys_id;
|
actor->sys_id = lacp->sys_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given 'slave', populates 'priority' with data representing its LACP link
|
/* Given 'member', populates 'priority' with data representing its LACP link
|
||||||
* priority. If two priority objects populated by this function are compared
|
* priority. If two priority objects populated by this function are compared
|
||||||
* using memcmp, the higher priority link will be less than the lower priority
|
* using memcmp, the higher priority link will be less than the lower priority
|
||||||
* link. */
|
* link. */
|
||||||
static void
|
static void
|
||||||
slave_get_priority(struct slave *slave, struct lacp_info *priority)
|
member_get_priority(struct member *member, struct lacp_info *priority)
|
||||||
OVS_REQUIRES(mutex)
|
OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
uint16_t partner_priority, actor_priority;
|
uint16_t partner_priority, actor_priority;
|
||||||
|
|
||||||
/* Choose the lacp_info of the higher priority system by comparing their
|
/* Choose the lacp_info of the higher priority system by comparing their
|
||||||
* system priorities and mac addresses. */
|
* system priorities and mac addresses. */
|
||||||
actor_priority = slave->lacp->sys_priority;
|
actor_priority = member->lacp->sys_priority;
|
||||||
partner_priority = ntohs(slave->partner.sys_priority);
|
partner_priority = ntohs(member->partner.sys_priority);
|
||||||
if (actor_priority < partner_priority) {
|
if (actor_priority < partner_priority) {
|
||||||
slave_get_actor(slave, priority);
|
member_get_actor(member, priority);
|
||||||
} else if (partner_priority < actor_priority) {
|
} else if (partner_priority < actor_priority) {
|
||||||
*priority = slave->partner;
|
*priority = member->partner;
|
||||||
} else if (eth_addr_compare_3way(slave->lacp->sys_id,
|
} else if (eth_addr_compare_3way(member->lacp->sys_id,
|
||||||
slave->partner.sys_id) < 0) {
|
member->partner.sys_id) < 0) {
|
||||||
slave_get_actor(slave, priority);
|
member_get_actor(member, priority);
|
||||||
} else {
|
} else {
|
||||||
*priority = slave->partner;
|
*priority = member->partner;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Key and state are not used in priority comparisons. */
|
/* Key and state are not used in priority comparisons. */
|
||||||
@ -864,22 +868,22 @@ slave_get_priority(struct slave *slave, struct lacp_info *priority)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
slave_may_tx(const struct slave *slave) OVS_REQUIRES(mutex)
|
member_may_tx(const struct member *member) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
/* Check for L1 state as well as LACP state. */
|
/* Check for L1 state as well as LACP state. */
|
||||||
return (slave->carrier_up) && ((slave->lacp->active) ||
|
return (member->carrier_up) && ((member->lacp->active) ||
|
||||||
(slave->status != LACP_DEFAULTED));
|
(member->status != LACP_DEFAULTED));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct slave *
|
static struct member *
|
||||||
slave_lookup(const struct lacp *lacp, const void *slave_) OVS_REQUIRES(mutex)
|
member_lookup(const struct lacp *lacp, const void *member_) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
|
|
||||||
HMAP_FOR_EACH_IN_BUCKET (slave, node, hash_pointer(slave_, 0),
|
HMAP_FOR_EACH_IN_BUCKET (member, node, hash_pointer(member_, 0),
|
||||||
&lacp->slaves) {
|
&lacp->members) {
|
||||||
if (slave->aux == slave_) {
|
if (member->aux == member_) {
|
||||||
return slave;
|
return member;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,10 +965,10 @@ ds_put_lacp_state(struct ds *ds, uint8_t state)
|
|||||||
static void
|
static void
|
||||||
lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
struct shash slave_shash = SHASH_INITIALIZER(&slave_shash);
|
struct shash member_shash = SHASH_INITIALIZER(&member_shash);
|
||||||
const struct shash_node **sorted_slaves = NULL;
|
const struct shash_node **sorted_members = NULL;
|
||||||
|
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ds_put_format(ds, "---- %s ----\n", lacp->name);
|
ds_put_format(ds, "---- %s ----\n", lacp->name);
|
||||||
@ -977,10 +981,10 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
ds_put_format(ds, " sys_id: " ETH_ADDR_FMT "\n", ETH_ADDR_ARGS(lacp->sys_id));
|
ds_put_format(ds, " sys_id: " ETH_ADDR_FMT "\n", ETH_ADDR_ARGS(lacp->sys_id));
|
||||||
ds_put_format(ds, " sys_priority: %u\n", lacp->sys_priority);
|
ds_put_format(ds, " sys_priority: %u\n", lacp->sys_priority);
|
||||||
ds_put_cstr(ds, " aggregation key: ");
|
ds_put_cstr(ds, " aggregation key: ");
|
||||||
if (lacp->key_slave) {
|
if (lacp->key_member) {
|
||||||
ds_put_format(ds, "%u", lacp->key_slave->key
|
ds_put_format(ds, "%u", lacp->key_member->key
|
||||||
? lacp->key_slave->key
|
? lacp->key_member->key
|
||||||
: lacp->key_slave->port_id);
|
: lacp->key_member->port_id);
|
||||||
} else {
|
} else {
|
||||||
ds_put_cstr(ds, "none");
|
ds_put_cstr(ds, "none");
|
||||||
}
|
}
|
||||||
@ -993,18 +997,18 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
ds_put_cstr(ds, "slow\n");
|
ds_put_cstr(ds, "slow\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
shash_add(&slave_shash, slave->name, slave);
|
shash_add(&member_shash, member->name, member);
|
||||||
}
|
}
|
||||||
sorted_slaves = shash_sort(&slave_shash);
|
sorted_members = shash_sort(&member_shash);
|
||||||
|
|
||||||
for (i = 0; i < shash_count(&slave_shash); i++) {
|
for (i = 0; i < shash_count(&member_shash); i++) {
|
||||||
char *status;
|
char *status;
|
||||||
struct lacp_info actor;
|
struct lacp_info actor;
|
||||||
|
|
||||||
slave = sorted_slaves[i]->data;
|
member = sorted_members[i]->data;
|
||||||
slave_get_actor(slave, &actor);
|
member_get_actor(member, &actor);
|
||||||
switch (slave->status) {
|
switch (member->status) {
|
||||||
case LACP_CURRENT:
|
case LACP_CURRENT:
|
||||||
status = "current";
|
status = "current";
|
||||||
break;
|
break;
|
||||||
@ -1018,11 +1022,11 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
OVS_NOT_REACHED();
|
OVS_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
ds_put_format(ds, "\nslave: %s: %s %s\n", slave->name, status,
|
ds_put_format(ds, "\nmember: %s: %s %s\n", member->name, status,
|
||||||
slave->attached ? "attached" : "detached");
|
member->attached ? "attached" : "detached");
|
||||||
ds_put_format(ds, " port_id: %u\n", slave->port_id);
|
ds_put_format(ds, " port_id: %u\n", member->port_id);
|
||||||
ds_put_format(ds, " port_priority: %u\n", slave->port_priority);
|
ds_put_format(ds, " port_priority: %u\n", member->port_priority);
|
||||||
ds_put_format(ds, " may_enable: %s\n", (slave_may_enable__(slave)
|
ds_put_format(ds, " may_enable: %s\n", (member_may_enable__(member)
|
||||||
? "true" : "false"));
|
? "true" : "false"));
|
||||||
|
|
||||||
ds_put_format(ds, "\n actor sys_id: " ETH_ADDR_FMT "\n",
|
ds_put_format(ds, "\n actor sys_id: " ETH_ADDR_FMT "\n",
|
||||||
@ -1040,58 +1044,58 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
|||||||
ds_put_cstr(ds, "\n\n");
|
ds_put_cstr(ds, "\n\n");
|
||||||
|
|
||||||
ds_put_format(ds, " partner sys_id: " ETH_ADDR_FMT "\n",
|
ds_put_format(ds, " partner sys_id: " ETH_ADDR_FMT "\n",
|
||||||
ETH_ADDR_ARGS(slave->partner.sys_id));
|
ETH_ADDR_ARGS(member->partner.sys_id));
|
||||||
ds_put_format(ds, " partner sys_priority: %u\n",
|
ds_put_format(ds, " partner sys_priority: %u\n",
|
||||||
ntohs(slave->partner.sys_priority));
|
ntohs(member->partner.sys_priority));
|
||||||
ds_put_format(ds, " partner port_id: %u\n",
|
ds_put_format(ds, " partner port_id: %u\n",
|
||||||
ntohs(slave->partner.port_id));
|
ntohs(member->partner.port_id));
|
||||||
ds_put_format(ds, " partner port_priority: %u\n",
|
ds_put_format(ds, " partner port_priority: %u\n",
|
||||||
ntohs(slave->partner.port_priority));
|
ntohs(member->partner.port_priority));
|
||||||
ds_put_format(ds, " partner key: %u\n",
|
ds_put_format(ds, " partner key: %u\n",
|
||||||
ntohs(slave->partner.key));
|
ntohs(member->partner.key));
|
||||||
ds_put_cstr(ds, " partner state:");
|
ds_put_cstr(ds, " partner state:");
|
||||||
ds_put_lacp_state(ds, slave->partner.state);
|
ds_put_lacp_state(ds, member->partner.state);
|
||||||
ds_put_cstr(ds, "\n");
|
ds_put_cstr(ds, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
shash_destroy(&slave_shash);
|
shash_destroy(&member_shash);
|
||||||
free(sorted_slaves);
|
free(sorted_members);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lacp_print_stats(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
lacp_print_stats(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
|
||||||
{
|
{
|
||||||
struct shash slave_shash = SHASH_INITIALIZER(&slave_shash);
|
struct shash member_shash = SHASH_INITIALIZER(&member_shash);
|
||||||
const struct shash_node **sorted_slaves = NULL;
|
const struct shash_node **sorted_members = NULL;
|
||||||
|
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ds_put_format(ds, "---- %s statistics ----\n", lacp->name);
|
ds_put_format(ds, "---- %s statistics ----\n", lacp->name);
|
||||||
|
|
||||||
HMAP_FOR_EACH (slave, node, &lacp->slaves) {
|
HMAP_FOR_EACH (member, node, &lacp->members) {
|
||||||
shash_add(&slave_shash, slave->name, slave);
|
shash_add(&member_shash, member->name, member);
|
||||||
}
|
}
|
||||||
sorted_slaves = shash_sort(&slave_shash);
|
sorted_members = shash_sort(&member_shash);
|
||||||
|
|
||||||
for (i = 0; i < shash_count(&slave_shash); i++) {
|
for (i = 0; i < shash_count(&member_shash); i++) {
|
||||||
slave = sorted_slaves[i]->data;
|
member = sorted_members[i]->data;
|
||||||
ds_put_format(ds, "\nslave: %s:\n", slave->name);
|
ds_put_format(ds, "\nmember: %s:\n", member->name);
|
||||||
ds_put_format(ds, " TX PDUs: %u\n", slave->count_tx_pdus);
|
ds_put_format(ds, " TX PDUs: %u\n", member->count_tx_pdus);
|
||||||
ds_put_format(ds, " RX PDUs: %u\n", slave->count_rx_pdus);
|
ds_put_format(ds, " RX PDUs: %u\n", member->count_rx_pdus);
|
||||||
ds_put_format(ds, " RX Bad PDUs: %u\n", slave->count_rx_pdus_bad);
|
ds_put_format(ds, " RX Bad PDUs: %u\n", member->count_rx_pdus_bad);
|
||||||
ds_put_format(ds, " RX Marker Request PDUs: %u\n",
|
ds_put_format(ds, " RX Marker Request PDUs: %u\n",
|
||||||
slave->count_rx_pdus_marker);
|
member->count_rx_pdus_marker);
|
||||||
ds_put_format(ds, " Link Expired: %u\n",
|
ds_put_format(ds, " Link Expired: %u\n",
|
||||||
slave->count_link_expired);
|
member->count_link_expired);
|
||||||
ds_put_format(ds, " Link Defaulted: %u\n",
|
ds_put_format(ds, " Link Defaulted: %u\n",
|
||||||
slave->count_link_defaulted);
|
member->count_link_defaulted);
|
||||||
ds_put_format(ds, " Carrier Status Changed: %u\n",
|
ds_put_format(ds, " Carrier Status Changed: %u\n",
|
||||||
slave->count_carrier_changed);
|
member->count_carrier_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
shash_destroy(&slave_shash);
|
shash_destroy(&member_shash);
|
||||||
free(sorted_slaves);
|
free(sorted_members);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1152,27 +1156,28 @@ out:
|
|||||||
lacp_unlock();
|
lacp_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract a snapshot of the current state and counters for a slave port.
|
/* Extract a snapshot of the current state and counters for a member port.
|
||||||
Return false if the slave is not active. */
|
Return false if the member is not active. */
|
||||||
bool
|
bool
|
||||||
lacp_get_slave_stats(const struct lacp *lacp, const void *slave_, struct lacp_slave_stats *stats)
|
lacp_get_member_stats(const struct lacp *lacp, const void *member_,
|
||||||
|
struct lacp_member_stats *stats)
|
||||||
OVS_EXCLUDED(mutex)
|
OVS_EXCLUDED(mutex)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
struct lacp_info actor;
|
struct lacp_info actor;
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
ovs_mutex_lock(&mutex);
|
ovs_mutex_lock(&mutex);
|
||||||
|
|
||||||
slave = slave_lookup(lacp, slave_);
|
member = member_lookup(lacp, member_);
|
||||||
if (slave) {
|
if (member) {
|
||||||
ret = true;
|
ret = true;
|
||||||
slave_get_actor(slave, &actor);
|
member_get_actor(member, &actor);
|
||||||
stats->dot3adAggPortActorSystemID = actor.sys_id;
|
stats->dot3adAggPortActorSystemID = actor.sys_id;
|
||||||
stats->dot3adAggPortPartnerOperSystemID = slave->partner.sys_id;
|
stats->dot3adAggPortPartnerOperSystemID = member->partner.sys_id;
|
||||||
stats->dot3adAggPortAttachedAggID = (lacp->key_slave->key ?
|
stats->dot3adAggPortAttachedAggID = (lacp->key_member->key ?
|
||||||
lacp->key_slave->key :
|
lacp->key_member->key :
|
||||||
lacp->key_slave->port_id);
|
lacp->key_member->port_id);
|
||||||
|
|
||||||
/* Construct my admin-state. Assume aggregation is configured on. */
|
/* Construct my admin-state. Assume aggregation is configured on. */
|
||||||
stats->dot3adAggPortActorAdminState = LACP_STATE_AGG;
|
stats->dot3adAggPortActorAdminState = LACP_STATE_AGG;
|
||||||
@ -1189,12 +1194,12 @@ lacp_get_slave_stats(const struct lacp *lacp, const void *slave_, struct lacp_sl
|
|||||||
stats->dot3adAggPortPartnerAdminState = 0;
|
stats->dot3adAggPortPartnerAdminState = 0;
|
||||||
|
|
||||||
stats->dot3adAggPortActorOperState = actor.state;
|
stats->dot3adAggPortActorOperState = actor.state;
|
||||||
stats->dot3adAggPortPartnerOperState = slave->partner.state;
|
stats->dot3adAggPortPartnerOperState = member->partner.state;
|
||||||
|
|
||||||
/* Read out the latest counters */
|
/* Read out the latest counters */
|
||||||
stats->dot3adAggPortStatsLACPDUsRx = slave->count_rx_pdus;
|
stats->dot3adAggPortStatsLACPDUsRx = member->count_rx_pdus;
|
||||||
stats->dot3adAggPortStatsIllegalRx = slave->count_rx_pdus_bad;
|
stats->dot3adAggPortStatsIllegalRx = member->count_rx_pdus_bad;
|
||||||
stats->dot3adAggPortStatsLACPDUsTx = slave->count_tx_pdus;
|
stats->dot3adAggPortStatsLACPDUsTx = member->count_tx_pdus;
|
||||||
} else {
|
} else {
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
23
lib/lacp.h
23
lib/lacp.h
@ -46,32 +46,32 @@ struct lacp *lacp_ref(const struct lacp *);
|
|||||||
void lacp_configure(struct lacp *, const struct lacp_settings *);
|
void lacp_configure(struct lacp *, const struct lacp_settings *);
|
||||||
bool lacp_is_active(const struct lacp *);
|
bool lacp_is_active(const struct lacp *);
|
||||||
|
|
||||||
bool lacp_process_packet(struct lacp *, const void *slave,
|
bool lacp_process_packet(struct lacp *, const void *member,
|
||||||
const struct dp_packet *packet);
|
const struct dp_packet *packet);
|
||||||
enum lacp_status lacp_status(const struct lacp *);
|
enum lacp_status lacp_status(const struct lacp *);
|
||||||
|
|
||||||
struct lacp_slave_settings {
|
struct lacp_member_settings {
|
||||||
char *name; /* Name (for debugging). */
|
char *name; /* Name (for debugging). */
|
||||||
uint16_t id; /* Port ID. */
|
uint16_t id; /* Port ID. */
|
||||||
uint16_t priority; /* Port priority. */
|
uint16_t priority; /* Port priority. */
|
||||||
uint16_t key; /* Aggregation key. */
|
uint16_t key; /* Aggregation key. */
|
||||||
};
|
};
|
||||||
|
|
||||||
void lacp_slave_register(struct lacp *, void *slave_,
|
void lacp_member_register(struct lacp *, void *member_,
|
||||||
const struct lacp_slave_settings *);
|
const struct lacp_member_settings *);
|
||||||
void lacp_slave_unregister(struct lacp *, const void *slave);
|
void lacp_member_unregister(struct lacp *, const void *member);
|
||||||
void lacp_slave_carrier_changed(const struct lacp *, const void *slave,
|
void lacp_member_carrier_changed(const struct lacp *, const void *member,
|
||||||
bool carrier_up);
|
bool carrier_up);
|
||||||
bool lacp_slave_may_enable(const struct lacp *, const void *slave);
|
bool lacp_member_may_enable(const struct lacp *, const void *member);
|
||||||
bool lacp_slave_is_current(const struct lacp *, const void *slave_);
|
bool lacp_member_is_current(const struct lacp *, const void *member_);
|
||||||
|
|
||||||
/* Callback function for lacp_run() for sending a LACP PDU. */
|
/* Callback function for lacp_run() for sending a LACP PDU. */
|
||||||
typedef void lacp_send_pdu(void *slave, const void *pdu, size_t pdu_size);
|
typedef void lacp_send_pdu(void *member, const void *pdu, size_t pdu_size);
|
||||||
|
|
||||||
void lacp_run(struct lacp *, lacp_send_pdu *);
|
void lacp_run(struct lacp *, lacp_send_pdu *);
|
||||||
void lacp_wait(struct lacp *);
|
void lacp_wait(struct lacp *);
|
||||||
|
|
||||||
struct lacp_slave_stats {
|
struct lacp_member_stats {
|
||||||
/* id */
|
/* id */
|
||||||
struct eth_addr dot3adAggPortActorSystemID;
|
struct eth_addr dot3adAggPortActorSystemID;
|
||||||
struct eth_addr dot3adAggPortPartnerOperSystemID;
|
struct eth_addr dot3adAggPortPartnerOperSystemID;
|
||||||
@ -92,6 +92,7 @@ struct lacp_slave_stats {
|
|||||||
/* uint32_t dot3adAggPortStatsMarkerResponsePDUsTx; */
|
/* uint32_t dot3adAggPortStatsMarkerResponsePDUsTx; */
|
||||||
};
|
};
|
||||||
|
|
||||||
bool lacp_get_slave_stats(const struct lacp *, const void *slave_, struct lacp_slave_stats *);
|
bool lacp_get_member_stats(const struct lacp *, const void *member_,
|
||||||
|
struct lacp_member_stats *);
|
||||||
|
|
||||||
#endif /* lacp.h */
|
#endif /* lacp.h */
|
||||||
|
@ -218,13 +218,13 @@
|
|||||||
#define LLDPD_MODE_MAX LLDPD_MODE_FDP
|
#define LLDPD_MODE_MAX LLDPD_MODE_FDP
|
||||||
|
|
||||||
|
|
||||||
/* Bond slave src mac type constants */
|
/* Bond member src mac type constants */
|
||||||
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_UNKNOWN 0
|
#define LLDP_BOND_MEMBER_SRC_MAC_TYPE_UNKNOWN 0
|
||||||
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_REAL 1
|
#define LLDP_BOND_MEMBER_SRC_MAC_TYPE_REAL 1
|
||||||
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_ZERO 2
|
#define LLDP_BOND_MEMBER_SRC_MAC_TYPE_ZERO 2
|
||||||
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_FIXED 3
|
#define LLDP_BOND_MEMBER_SRC_MAC_TYPE_FIXED 3
|
||||||
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED 4
|
#define LLDP_BOND_MEMBER_SRC_MAC_TYPE_LOCALLY_ADMINISTERED 4
|
||||||
#define LLDP_BOND_SLAVE_SRC_MAC_TYPE_MAX \
|
#define LLDP_BOND_MEMBER_SRC_MAC_TYPE_MAX \
|
||||||
LLDP_BOND_SLAVE_SRC_MAC_TYPE_LOCALLY_ADMINISTERED
|
LLDP_BOND_MEMBER_SRC_MAC_TYPE_LOCALLY_ADMINISTERED
|
||||||
|
|
||||||
#endif /* _LLDP_H */
|
#endif /* _LLDP_H */
|
||||||
|
@ -135,8 +135,8 @@ struct lldpd_config {
|
|||||||
int c_set_ifdescr; /* Set interface description */
|
int c_set_ifdescr; /* Set interface description */
|
||||||
int c_promisc; /* Interfaces should be in promiscuous mode */
|
int c_promisc; /* Interfaces should be in promiscuous mode */
|
||||||
int c_tx_hold; /* Transmit hold */
|
int c_tx_hold; /* Transmit hold */
|
||||||
int c_bond_slave_src_mac_type; /* Src mac type in lldp frames over bond
|
int c_bond_member_src_mac_type; /* Src mac type in lldp frames over bond
|
||||||
* slaves */
|
* member interfaces */
|
||||||
int c_lldp_portid_type; /* The PortID type */
|
int c_lldp_portid_type; /* The PortID type */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,9 +158,9 @@ struct lldpd_ops {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* An interface is uniquely identified by h_ifindex, h_ifname and h_ops. This
|
/* An interface is uniquely identified by h_ifindex, h_ifname and h_ops. This
|
||||||
* means if an interface becomes enslaved, it will be considered as a new
|
* means if an interface becomes a bond member, it will be considered as a
|
||||||
* interface. The same applies for renaming and we include the index in case of
|
* new interface. The same applies for renaming and we include the index in
|
||||||
* renaming to an existing interface.
|
* case of renaming to an existing interface.
|
||||||
*/
|
*/
|
||||||
struct lldpd_hardware {
|
struct lldpd_hardware {
|
||||||
struct ovs_list h_entries;
|
struct ovs_list h_entries;
|
||||||
|
@ -384,7 +384,7 @@ is_mac_learning_update_needed(const struct mac_learning *ml,
|
|||||||
|
|
||||||
if (is_gratuitous_arp) {
|
if (is_gratuitous_arp) {
|
||||||
/* We don't want to learn from gratuitous ARP packets that are
|
/* We don't want to learn from gratuitous ARP packets that are
|
||||||
* reflected back over bond slaves so we lock the learning table. For
|
* reflected back over bond members so we lock the learning table. For
|
||||||
* more detail, see the bigger comment in update_learning_table__(). */
|
* more detail, see the bigger comment in update_learning_table__(). */
|
||||||
if (!is_bond) {
|
if (!is_bond) {
|
||||||
return true; /* Need to set the gratuitous ARP lock. */
|
return true; /* Need to set the gratuitous ARP lock. */
|
||||||
@ -424,7 +424,7 @@ update_learning_table__(struct mac_learning *ml, struct eth_addr src,
|
|||||||
mac = mac_learning_insert(ml, src, vlan);
|
mac = mac_learning_insert(ml, src, vlan);
|
||||||
if (is_gratuitous_arp) {
|
if (is_gratuitous_arp) {
|
||||||
/* Gratuitous ARP packets received over non-bond interfaces could be
|
/* Gratuitous ARP packets received over non-bond interfaces could be
|
||||||
* reflected back over bond slaves. We don't want to learn from these
|
* reflected back over bond members. We don't want to learn from these
|
||||||
* reflected packets, so we lock each entry for which a gratuitous ARP
|
* reflected packets, so we lock each entry for which a gratuitous ARP
|
||||||
* packet was received over a non-bond interface and refrain from
|
* packet was received over a non-bond interface and refrain from
|
||||||
* learning from gratuitous ARP packets that arrive over bond
|
* learning from gratuitous ARP packets that arrive over bond
|
||||||
|
@ -95,7 +95,7 @@ struct mac_learning;
|
|||||||
#define MAC_ENTRY_DEFAULT_IDLE_TIME 300
|
#define MAC_ENTRY_DEFAULT_IDLE_TIME 300
|
||||||
|
|
||||||
/* Time, in seconds, to lock an entry updated by a gratuitous ARP to avoid
|
/* Time, in seconds, to lock an entry updated by a gratuitous ARP to avoid
|
||||||
* relearning based on a reflection from a bond slave. */
|
* relearning based on a reflection from a bond member. */
|
||||||
#define MAC_GRAT_ARP_LOCK_TIME 5
|
#define MAC_GRAT_ARP_LOCK_TIME 5
|
||||||
|
|
||||||
/* A MAC learning table entry.
|
/* A MAC learning table entry.
|
||||||
|
@ -257,15 +257,15 @@ enum {
|
|||||||
IOV_AUXBUF = 1,
|
IOV_AUXBUF = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_lag_slave {
|
struct linux_lag_member {
|
||||||
uint32_t block_id;
|
uint32_t block_id;
|
||||||
struct shash_node *node;
|
struct shash_node *node;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Protects 'lag_shash' and the mutable members of struct linux_lag_slave. */
|
/* Protects 'lag_shash' and the mutable members of struct linux_lag_member. */
|
||||||
static struct ovs_mutex lag_mutex = OVS_MUTEX_INITIALIZER;
|
static struct ovs_mutex lag_mutex = OVS_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
/* All slaves whose LAG masters are network devices in OvS. */
|
/* All members whose LAG primary interfaces are OVS network devices. */
|
||||||
static struct shash lag_shash OVS_GUARDED_BY(lag_mutex)
|
static struct shash lag_shash OVS_GUARDED_BY(lag_mutex)
|
||||||
= SHASH_INITIALIZER(&lag_shash);
|
= SHASH_INITIALIZER(&lag_shash);
|
||||||
|
|
||||||
@ -661,9 +661,9 @@ static void
|
|||||||
netdev_linux_update_lag(struct rtnetlink_change *change)
|
netdev_linux_update_lag(struct rtnetlink_change *change)
|
||||||
OVS_REQUIRES(lag_mutex)
|
OVS_REQUIRES(lag_mutex)
|
||||||
{
|
{
|
||||||
struct linux_lag_slave *lag;
|
struct linux_lag_member *lag;
|
||||||
|
|
||||||
if (change->slave && netdev_linux_kind_is_lag(change->slave)) {
|
if (change->sub && netdev_linux_kind_is_lag(change->sub)) {
|
||||||
lag = shash_find_data(&lag_shash, change->ifname);
|
lag = shash_find_data(&lag_shash, change->ifname);
|
||||||
|
|
||||||
if (!lag) {
|
if (!lag) {
|
||||||
@ -691,12 +691,12 @@ netdev_linux_update_lag(struct rtnetlink_change *change)
|
|||||||
|
|
||||||
/* delete ingress block in case it exists */
|
/* delete ingress block in case it exists */
|
||||||
tc_add_del_qdisc(change->if_index, false, 0, TC_INGRESS);
|
tc_add_del_qdisc(change->if_index, false, 0, TC_INGRESS);
|
||||||
/* LAG master is linux netdev so add slave to same block. */
|
/* LAG master is linux netdev so add member to same block. */
|
||||||
error = tc_add_del_qdisc(change->if_index, true, block_id,
|
error = tc_add_del_qdisc(change->if_index, true, block_id,
|
||||||
TC_INGRESS);
|
TC_INGRESS);
|
||||||
if (error) {
|
if (error) {
|
||||||
VLOG_WARN("failed to bind LAG slave %s to master's block",
|
VLOG_WARN("failed to bind LAG member %s to "
|
||||||
change->ifname);
|
"primary's block", change->ifname);
|
||||||
shash_delete(&lag_shash, lag->node);
|
shash_delete(&lag_shash, lag->node);
|
||||||
free(lag);
|
free(lag);
|
||||||
}
|
}
|
||||||
@ -705,7 +705,7 @@ netdev_linux_update_lag(struct rtnetlink_change *change)
|
|||||||
netdev_close(master_netdev);
|
netdev_close(master_netdev);
|
||||||
}
|
}
|
||||||
} else if (change->master_ifindex == 0) {
|
} else if (change->master_ifindex == 0) {
|
||||||
/* Check if this was a lag slave that has been freed. */
|
/* Check if this was a lag member that has been removed. */
|
||||||
lag = shash_find_data(&lag_shash, change->ifname);
|
lag = shash_find_data(&lag_shash, change->ifname);
|
||||||
|
|
||||||
if (lag) {
|
if (lag) {
|
||||||
@ -860,7 +860,7 @@ netdev_linux_update__(struct netdev_linux *dev,
|
|||||||
rtnetlink_report_link();
|
rtnetlink_report_link();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change->master && netdev_linux_kind_is_lag(change->master)) {
|
if (change->primary && netdev_linux_kind_is_lag(change->primary)) {
|
||||||
dev->is_lag_master = true;
|
dev->is_lag_master = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6376,7 +6376,7 @@ netdev_linux_update_via_netlink(struct netdev_linux *netdev)
|
|||||||
netdev->get_ifindex_error = 0;
|
netdev->get_ifindex_error = 0;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
if (change->master && netdev_linux_kind_is_lag(change->master)) {
|
if (change->primary && netdev_linux_kind_is_lag(change->primary)) {
|
||||||
netdev->is_lag_master = true;
|
netdev->is_lag_master = true;
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
@ -1334,39 +1334,39 @@ check_OUTPUT_REG(const struct ofpact_output_reg *a,
|
|||||||
|
|
||||||
/* Action structure for NXAST_BUNDLE and NXAST_BUNDLE_LOAD.
|
/* Action structure for NXAST_BUNDLE and NXAST_BUNDLE_LOAD.
|
||||||
*
|
*
|
||||||
* The bundle actions choose a slave from a supplied list of options.
|
* The bundle actions choose a member from a supplied list of options.
|
||||||
* NXAST_BUNDLE outputs to its selection. NXAST_BUNDLE_LOAD writes its
|
* NXAST_BUNDLE outputs to its selection. NXAST_BUNDLE_LOAD writes its
|
||||||
* selection to a register.
|
* selection to a register.
|
||||||
*
|
*
|
||||||
* The list of possible slaves follows the nx_action_bundle structure. The size
|
* The list of possible members follows the nx_action_bundle structure. The
|
||||||
* of each slave is governed by its type as indicated by the 'slave_type'
|
* size of each member is governed by its type as indicated by the
|
||||||
* parameter. The list of slaves should be padded at its end with zeros to make
|
* 'member_type' parameter. The list of members should be padded at its end
|
||||||
* the total length of the action a multiple of 8.
|
* with zeros to make the total length of the action a multiple of 8.
|
||||||
*
|
*
|
||||||
* Switches infer from the 'slave_type' parameter the size of each slave. All
|
* Switches infer from the 'member_type' parameter the size of each member.
|
||||||
* implementations must support the NXM_OF_IN_PORT 'slave_type' which indicates
|
* All implementations must support the NXM_OF_IN_PORT 'member_type' which
|
||||||
* that the slaves are OpenFlow port numbers with NXM_LENGTH(NXM_OF_IN_PORT) ==
|
* indicates that the members are OpenFlow port numbers with
|
||||||
* 2 byte width. Switches should reject actions which indicate unknown or
|
* NXM_LENGTH(NXM_OF_IN_PORT) == 2 byte width. Switches should reject actions
|
||||||
* unsupported slave types.
|
* which indicate unknown or unsupported member types.
|
||||||
*
|
*
|
||||||
* Switches use a strategy dictated by the 'algorithm' parameter to choose a
|
* Switches use a strategy dictated by the 'algorithm' parameter to choose a
|
||||||
* slave. If the switch does not support the specified 'algorithm' parameter,
|
* member. If the switch does not support the specified 'algorithm' parameter,
|
||||||
* it should reject the action.
|
* it should reject the action.
|
||||||
*
|
*
|
||||||
* Several algorithms take into account liveness when selecting slaves. The
|
* Several algorithms take into account liveness when selecting members. The
|
||||||
* liveness of a slave is implementation defined (with one exception), but will
|
* liveness of a member is implementation defined (with one exception), but
|
||||||
* generally take into account things like its carrier status and the results
|
* will generally take into account things like its carrier status and the
|
||||||
* of any link monitoring protocols which happen to be running on it. In order
|
* results of any link monitoring protocols which happen to be running on it.
|
||||||
* to give controllers a place-holder value, the OFPP_NONE port is always
|
* In order to give controllers a place-holder value, the OFPP_NONE port is
|
||||||
* considered live, that is, NXAST_BUNDLE_LOAD stores OFPP_NONE in the output
|
* always considered live, that is, NXAST_BUNDLE_LOAD stores OFPP_NONE in the
|
||||||
* register if no slave is live.
|
* output register if no member is live.
|
||||||
*
|
*
|
||||||
* Some slave selection strategies require the use of a hash function, in which
|
* Some member selection strategies require the use of a hash function, in
|
||||||
* case the 'fields' and 'basis' parameters should be populated. The 'fields'
|
* which case the 'fields' and 'basis' parameters should be populated. The
|
||||||
* parameter (one of NX_HASH_FIELDS_*) designates which parts of the flow to
|
* 'fields' parameter (one of NX_HASH_FIELDS_*) designates which parts of the
|
||||||
* hash. Refer to the definition of "enum nx_hash_fields" for details. The
|
* flow to hash. Refer to the definition of "enum nx_hash_fields" for details.
|
||||||
* 'basis' parameter is used as a universal hash parameter. Different values
|
* The 'basis' parameter is used as a universal hash parameter. Different
|
||||||
* of 'basis' yield different hash results.
|
* values of 'basis' yield different hash results.
|
||||||
*
|
*
|
||||||
* The 'zero' parameter at the end of the action structure is reserved for
|
* The 'zero' parameter at the end of the action structure is reserved for
|
||||||
* future use. Switches are required to reject actions which have nonzero
|
* future use. Switches are required to reject actions which have nonzero
|
||||||
@ -1375,24 +1375,24 @@ check_OUTPUT_REG(const struct ofpact_output_reg *a,
|
|||||||
* NXAST_BUNDLE actions should have 'ofs_nbits' and 'dst' zeroed. Switches
|
* NXAST_BUNDLE actions should have 'ofs_nbits' and 'dst' zeroed. Switches
|
||||||
* should reject actions which have nonzero bytes in either of these fields.
|
* should reject actions which have nonzero bytes in either of these fields.
|
||||||
*
|
*
|
||||||
* NXAST_BUNDLE_LOAD stores the OpenFlow port number of the selected slave in
|
* NXAST_BUNDLE_LOAD stores the OpenFlow port number of the selected member in
|
||||||
* dst[ofs:ofs+n_bits]. The format and semantics of 'dst' and 'ofs_nbits' are
|
* dst[ofs:ofs+n_bits]. The format and semantics of 'dst' and 'ofs_nbits' are
|
||||||
* similar to those for the NXAST_REG_LOAD action. */
|
* similar to those for the NXAST_REG_LOAD action. */
|
||||||
struct nx_action_bundle {
|
struct nx_action_bundle {
|
||||||
ovs_be16 type; /* OFPAT_VENDOR. */
|
ovs_be16 type; /* OFPAT_VENDOR. */
|
||||||
ovs_be16 len; /* Length including slaves. */
|
ovs_be16 len; /* Length including members. */
|
||||||
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
||||||
ovs_be16 subtype; /* NXAST_BUNDLE or NXAST_BUNDLE_LOAD. */
|
ovs_be16 subtype; /* NXAST_BUNDLE or NXAST_BUNDLE_LOAD. */
|
||||||
|
|
||||||
/* Slave choice algorithm to apply to hash value. */
|
/* Member choice algorithm to apply to hash value. */
|
||||||
ovs_be16 algorithm; /* One of NX_BD_ALG_*. */
|
ovs_be16 algorithm; /* One of NX_BD_ALG_*. */
|
||||||
|
|
||||||
/* What fields to hash and how. */
|
/* What fields to hash and how. */
|
||||||
ovs_be16 fields; /* One of NX_HASH_FIELDS_*. */
|
ovs_be16 fields; /* One of NX_HASH_FIELDS_*. */
|
||||||
ovs_be16 basis; /* Universal hash parameter. */
|
ovs_be16 basis; /* Universal hash parameter. */
|
||||||
|
|
||||||
ovs_be32 slave_type; /* NXM_OF_IN_PORT. */
|
ovs_be32 member_type; /* NXM_OF_IN_PORT. */
|
||||||
ovs_be16 n_slaves; /* Number of slaves. */
|
ovs_be16 n_members; /* Number of members. */
|
||||||
|
|
||||||
ovs_be16 ofs_nbits; /* (ofs << 6) | (n_bits - 1). */
|
ovs_be16 ofs_nbits; /* (ofs << 6) | (n_bits - 1). */
|
||||||
ovs_be32 dst; /* Destination. */
|
ovs_be32 dst; /* Destination. */
|
||||||
@ -1408,29 +1408,29 @@ decode_bundle(bool load, const struct nx_action_bundle *nab,
|
|||||||
{
|
{
|
||||||
static struct vlog_rate_limit rll = VLOG_RATE_LIMIT_INIT(1, 5);
|
static struct vlog_rate_limit rll = VLOG_RATE_LIMIT_INIT(1, 5);
|
||||||
struct ofpact_bundle *bundle;
|
struct ofpact_bundle *bundle;
|
||||||
uint32_t slave_type;
|
uint32_t member_type;
|
||||||
size_t slaves_size, i;
|
size_t members_size, i;
|
||||||
enum ofperr error;
|
enum ofperr error;
|
||||||
|
|
||||||
bundle = ofpact_put_BUNDLE(ofpacts);
|
bundle = ofpact_put_BUNDLE(ofpacts);
|
||||||
|
|
||||||
bundle->n_slaves = ntohs(nab->n_slaves);
|
bundle->n_members = ntohs(nab->n_members);
|
||||||
bundle->basis = ntohs(nab->basis);
|
bundle->basis = ntohs(nab->basis);
|
||||||
bundle->fields = ntohs(nab->fields);
|
bundle->fields = ntohs(nab->fields);
|
||||||
bundle->algorithm = ntohs(nab->algorithm);
|
bundle->algorithm = ntohs(nab->algorithm);
|
||||||
slave_type = ntohl(nab->slave_type);
|
member_type = ntohl(nab->member_type);
|
||||||
slaves_size = ntohs(nab->len) - sizeof *nab;
|
members_size = ntohs(nab->len) - sizeof *nab;
|
||||||
|
|
||||||
error = OFPERR_OFPBAC_BAD_ARGUMENT;
|
error = OFPERR_OFPBAC_BAD_ARGUMENT;
|
||||||
if (!flow_hash_fields_valid(bundle->fields)) {
|
if (!flow_hash_fields_valid(bundle->fields)) {
|
||||||
VLOG_WARN_RL(&rll, "unsupported fields %d", (int) bundle->fields);
|
VLOG_WARN_RL(&rll, "unsupported fields %d", (int) bundle->fields);
|
||||||
} else if (bundle->n_slaves > BUNDLE_MAX_SLAVES) {
|
} else if (bundle->n_members > BUNDLE_MAX_MEMBERS) {
|
||||||
VLOG_WARN_RL(&rll, "too many slaves");
|
VLOG_WARN_RL(&rll, "too many members");
|
||||||
} else if (bundle->algorithm != NX_BD_ALG_HRW
|
} else if (bundle->algorithm != NX_BD_ALG_HRW
|
||||||
&& bundle->algorithm != NX_BD_ALG_ACTIVE_BACKUP) {
|
&& bundle->algorithm != NX_BD_ALG_ACTIVE_BACKUP) {
|
||||||
VLOG_WARN_RL(&rll, "unsupported algorithm %d", (int) bundle->algorithm);
|
VLOG_WARN_RL(&rll, "unsupported algorithm %d", (int) bundle->algorithm);
|
||||||
} else if (slave_type != mf_nxm_header(MFF_IN_PORT)) {
|
} else if (member_type != mf_nxm_header(MFF_IN_PORT)) {
|
||||||
VLOG_WARN_RL(&rll, "unsupported slave type %"PRIu32, slave_type);
|
VLOG_WARN_RL(&rll, "unsupported member type %"PRIu32, member_type);
|
||||||
} else {
|
} else {
|
||||||
error = 0;
|
error = 0;
|
||||||
}
|
}
|
||||||
@ -1461,15 +1461,15 @@ decode_bundle(bool load, const struct nx_action_bundle *nab,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slaves_size < bundle->n_slaves * sizeof(ovs_be16)) {
|
if (members_size < bundle->n_members * sizeof(ovs_be16)) {
|
||||||
VLOG_WARN_RL(&rll, "Nicira action %s only has %"PRIuSIZE" bytes "
|
VLOG_WARN_RL(&rll, "Nicira action %s only has %"PRIuSIZE" bytes "
|
||||||
"allocated for slaves. %"PRIuSIZE" bytes are required "
|
"allocated for members. %"PRIuSIZE" bytes are "
|
||||||
"for %u slaves.",
|
"required for %u members.",
|
||||||
load ? "bundle_load" : "bundle", slaves_size,
|
load ? "bundle_load" : "bundle", members_size,
|
||||||
bundle->n_slaves * sizeof(ovs_be16), bundle->n_slaves);
|
bundle->n_members * sizeof(ovs_be16), bundle->n_members);
|
||||||
error = OFPERR_OFPBAC_BAD_LEN;
|
error = OFPERR_OFPBAC_BAD_LEN;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
ofp_port_t ofp_port
|
ofp_port_t ofp_port
|
||||||
= u16_to_ofp(ntohs(((ovs_be16 *)(nab + 1))[i]));
|
= u16_to_ofp(ntohs(((ovs_be16 *)(nab + 1))[i]));
|
||||||
ofpbuf_put(ofpacts, &ofp_port, sizeof ofp_port);
|
ofpbuf_put(ofpacts, &ofp_port, sizeof ofp_port);
|
||||||
@ -1506,29 +1506,29 @@ encode_BUNDLE(const struct ofpact_bundle *bundle,
|
|||||||
enum ofp_version ofp_version OVS_UNUSED,
|
enum ofp_version ofp_version OVS_UNUSED,
|
||||||
struct ofpbuf *out)
|
struct ofpbuf *out)
|
||||||
{
|
{
|
||||||
int slaves_len = ROUND_UP(2 * bundle->n_slaves, OFP_ACTION_ALIGN);
|
int members_len = ROUND_UP(2 * bundle->n_members, OFP_ACTION_ALIGN);
|
||||||
struct nx_action_bundle *nab;
|
struct nx_action_bundle *nab;
|
||||||
ovs_be16 *slaves;
|
ovs_be16 *members;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
nab = (bundle->dst.field
|
nab = (bundle->dst.field
|
||||||
? put_NXAST_BUNDLE_LOAD(out)
|
? put_NXAST_BUNDLE_LOAD(out)
|
||||||
: put_NXAST_BUNDLE(out));
|
: put_NXAST_BUNDLE(out));
|
||||||
nab->len = htons(ntohs(nab->len) + slaves_len);
|
nab->len = htons(ntohs(nab->len) + members_len);
|
||||||
nab->algorithm = htons(bundle->algorithm);
|
nab->algorithm = htons(bundle->algorithm);
|
||||||
nab->fields = htons(bundle->fields);
|
nab->fields = htons(bundle->fields);
|
||||||
nab->basis = htons(bundle->basis);
|
nab->basis = htons(bundle->basis);
|
||||||
nab->slave_type = htonl(mf_nxm_header(MFF_IN_PORT));
|
nab->member_type = htonl(mf_nxm_header(MFF_IN_PORT));
|
||||||
nab->n_slaves = htons(bundle->n_slaves);
|
nab->n_members = htons(bundle->n_members);
|
||||||
if (bundle->dst.field) {
|
if (bundle->dst.field) {
|
||||||
nab->ofs_nbits = nxm_encode_ofs_nbits(bundle->dst.ofs,
|
nab->ofs_nbits = nxm_encode_ofs_nbits(bundle->dst.ofs,
|
||||||
bundle->dst.n_bits);
|
bundle->dst.n_bits);
|
||||||
nab->dst = htonl(nxm_header_from_mff(bundle->dst.field));
|
nab->dst = htonl(nxm_header_from_mff(bundle->dst.field));
|
||||||
}
|
}
|
||||||
|
|
||||||
slaves = ofpbuf_put_zeros(out, slaves_len);
|
members = ofpbuf_put_zeros(out, members_len);
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
slaves[i] = htons(ofp_to_u16(bundle->slaves[i]));
|
members[i] = htons(ofp_to_u16(bundle->members[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3585,7 +3585,7 @@ check_STACK_POP(const struct ofpact_stack *a,
|
|||||||
*/
|
*/
|
||||||
struct nx_action_cnt_ids {
|
struct nx_action_cnt_ids {
|
||||||
ovs_be16 type; /* OFPAT_VENDOR. */
|
ovs_be16 type; /* OFPAT_VENDOR. */
|
||||||
ovs_be16 len; /* Length including slaves. */
|
ovs_be16 len; /* Length including cnt_ids. */
|
||||||
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
||||||
ovs_be16 subtype; /* NXAST_DEC_TTL_CNT_IDS. */
|
ovs_be16 subtype; /* NXAST_DEC_TTL_CNT_IDS. */
|
||||||
|
|
||||||
|
@ -789,15 +789,16 @@ $ ovs-ofctl -O OpenFlow10 add-flow br0 actions=mod_nw_src:1.2.3.4
|
|||||||
|
|
||||||
<action name="BUNDLE,BUNDLE_LOAD">
|
<action name="BUNDLE,BUNDLE_LOAD">
|
||||||
<h2>The <code>bundle</code> and <code>bundle_load</code> actions</h2>
|
<h2>The <code>bundle</code> and <code>bundle_load</code> actions</h2>
|
||||||
<syntax><code>bundle(</code><var>fields</var><code>, </code><var>basis</var><code>, </code><var>algorithm</var><code>, ofport, slaves:</code><var>port</var>...<code>)</code></syntax>
|
<syntax><code>bundle(</code><var>fields</var><code>, </code><var>basis</var><code>, </code><var>algorithm</var><code>, ofport, members:</code><var>port</var>...<code>)</code></syntax>
|
||||||
<syntax><code>bundle_load(</code><var>fields</var><code>, </code><var>basis</var><code>, </code><var>algorithm</var><code>, ofport, </code><var>dst</var><code>, slaves:</code><var>port</var>...<code>)</code></syntax>
|
<syntax><code>bundle_load(</code><var>fields</var><code>, </code><var>basis</var><code>, </code><var>algorithm</var><code>, ofport, </code><var>dst</var><code>, members:</code><var>port</var>...<code>)</code></syntax>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
These actions choose a port (``slave'') from a comma-separated OpenFlow
|
These actions choose a port (a ``member'') from a
|
||||||
<var>port</var> list. After selecting the port, <code>bundle</code>
|
comma-separated OpenFlow <var>port</var> list. After selecting the
|
||||||
outputs to it, whereas <code>bundle_load</code> writes its port number
|
port, <code>bundle</code> outputs to it, whereas
|
||||||
to <var>dst</var>, which must be a 16-bit or wider field or subfield in
|
<code>bundle_load</code> writes its port number to <var>dst</var>,
|
||||||
the syntax described under ``Field Specifications'' above.
|
which must be a 16-bit or wider field or subfield in the syntax
|
||||||
|
described under ``Field Specifications'' above.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -854,20 +855,20 @@ $ ovs-ofctl -O OpenFlow10 add-flow br0 actions=mod_nw_src:1.2.3.4
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><code>active_backup</code></dt>
|
<dt><code>active_backup</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Chooses the first live port listed in <var>slaves</var>.
|
Chooses the first live port listed in <var>members</var>.
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><code>hrw</code> (Highest Random Weight)</dt>
|
<dt><code>hrw</code> (Highest Random Weight)</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p>
|
<p>
|
||||||
Computes the following, considering only the live ports in
|
Computes the following, considering only the live ports in
|
||||||
<var>slaves</var>:
|
<var>members</var>:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
for <var>i</var> in [1,<var>n_slaves</var>]:
|
for <var>i</var> in [1,<var>n_members</var>]:
|
||||||
<var>weights</var>[<var>i</var>] = hash(<var>flow</var>, <var>i</var>)
|
<var>weights</var>[<var>i</var>] = hash(<var>flow</var>, <var>i</var>)
|
||||||
<var>slave</var> = { <var>i</var> such that <var>weights</var>[<var>i</var>] >= <var>weights</var>[<var>j</var>] for all <var>j</var> != <var>i</var> }
|
<var>member</var> = { <var>i</var> such that <var>weights</var>[<var>i</var>] >= <var>weights</var>[<var>j</var>] for all <var>j</var> != <var>i</var> }
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@ -877,17 +878,17 @@ for <var>i</var> in [1,<var>n_slaves</var>]:
|
|||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The algorithms take port liveness into account when selecting slaves.
|
The algorithms take port liveness into account when selecting
|
||||||
The definition of whether a port is live is subject to change. It
|
members. The definition of whether a port is live is subject to
|
||||||
currently takes into account carrier status and link monitoring
|
change. It currently takes into account carrier status and link
|
||||||
protocols such as BFD and CFM. If none of the slaves is live,
|
monitoring protocols such as BFD and CFM. If none of the members is
|
||||||
<code>bundle</code> does not output the packet and
|
live, <code>bundle</code> does not output the packet and
|
||||||
<code>bundle_load</code> stores <code>OFPP_NONE</code> (65535) in the
|
<code>bundle_load</code> stores <code>OFPP_NONE</code> (65535) in the
|
||||||
output field.
|
output field.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Example: <code>bundle(eth_src,0,hrw,ofport,slaves:4,8)</code> uses an
|
Example: <code>bundle(eth_src,0,hrw,ofport,members:4,8)</code> uses an
|
||||||
Ethernet source hash with basis 0, to select between OpenFlow ports 4
|
Ethernet source hash with basis 0, to select between OpenFlow ports 4
|
||||||
and 8 using the Highest Random Weight algorithm.
|
and 8 using the Highest Random Weight algorithm.
|
||||||
</p>
|
</p>
|
||||||
|
@ -68,10 +68,10 @@ rtnetlink_parse_link_info(const struct nlattr *nla,
|
|||||||
ARRAY_SIZE(linkinfo_policy));
|
ARRAY_SIZE(linkinfo_policy));
|
||||||
|
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
change->master = (linkinfo[IFLA_INFO_KIND]
|
change->primary = (linkinfo[IFLA_INFO_KIND]
|
||||||
? nl_attr_get_string(linkinfo[IFLA_INFO_KIND])
|
? nl_attr_get_string(linkinfo[IFLA_INFO_KIND])
|
||||||
: NULL);
|
: NULL);
|
||||||
change->slave = (linkinfo[IFLA_INFO_SLAVE_KIND]
|
change->sub = (linkinfo[IFLA_INFO_SLAVE_KIND]
|
||||||
? nl_attr_get_string(linkinfo[IFLA_INFO_SLAVE_KIND])
|
? nl_attr_get_string(linkinfo[IFLA_INFO_SLAVE_KIND])
|
||||||
: NULL);
|
: NULL);
|
||||||
}
|
}
|
||||||
@ -134,8 +134,8 @@ rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
|
|||||||
parsed = rtnetlink_parse_link_info(attrs[IFLA_LINKINFO],
|
parsed = rtnetlink_parse_link_info(attrs[IFLA_LINKINFO],
|
||||||
change);
|
change);
|
||||||
} else {
|
} else {
|
||||||
change->master = NULL;
|
change->primary = NULL;
|
||||||
change->slave = NULL;
|
change->sub = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (rtnetlink_type_is_rtnlgrp_addr(nlmsg->nlmsg_type)) {
|
} else if (rtnetlink_type_is_rtnlgrp_addr(nlmsg->nlmsg_type)) {
|
||||||
|
@ -49,9 +49,9 @@ struct rtnetlink_change {
|
|||||||
/* Network device address status. */
|
/* Network device address status. */
|
||||||
/* xxx To be added when needed. */
|
/* xxx To be added when needed. */
|
||||||
|
|
||||||
/* Link info. */
|
/* Link bonding info. */
|
||||||
const char *master; /* Kind of master (NULL if not master). */
|
const char *primary; /* Kind of primary (NULL if not primary). */
|
||||||
const char *slave; /* Kind of slave (NULL if not slave). */
|
const char *sub; /* Kind of subordinate (NULL if not sub). */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Function called to report that a netdev has changed. 'change' describes the
|
/* Function called to report that a netdev has changed. 'change' describes the
|
||||||
|
@ -77,8 +77,10 @@ unixctl_list_commands(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
|||||||
const struct shash_node *node = nodes[i];
|
const struct shash_node *node = nodes[i];
|
||||||
const struct unixctl_command *command = node->data;
|
const struct unixctl_command *command = node->data;
|
||||||
|
|
||||||
|
if (command->usage) {
|
||||||
ds_put_format(&ds, " %-23s %s\n", node->name, command->usage);
|
ds_put_format(&ds, " %-23s %s\n", node->name, command->usage);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
free(nodes);
|
free(nodes);
|
||||||
|
|
||||||
unixctl_command_reply(conn, ds_cstr(&ds));
|
unixctl_command_reply(conn, ds_cstr(&ds));
|
||||||
@ -94,7 +96,7 @@ unixctl_version(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
|||||||
|
|
||||||
/* Registers a unixctl command with the given 'name'. 'usage' describes the
|
/* Registers a unixctl command with the given 'name'. 'usage' describes the
|
||||||
* arguments to the command; it is used only for presentation to the user in
|
* arguments to the command; it is used only for presentation to the user in
|
||||||
* "list-commands" output.
|
* "list-commands" output. (If 'usage' is NULL, then the command is hidden.)
|
||||||
*
|
*
|
||||||
* 'cb' is called when the command is received. It is passed an array
|
* 'cb' is called when the command is received. It is passed an array
|
||||||
* containing the command name and arguments, plus a copy of 'aux'. Normally
|
* containing the command name and arguments, plus a copy of 'aux'. Normally
|
||||||
|
815
ofproto/bond.c
815
ofproto/bond.c
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,7 @@ struct ofpbuf;
|
|||||||
struct ofproto_dpif;
|
struct ofproto_dpif;
|
||||||
enum lacp_status;
|
enum lacp_status;
|
||||||
|
|
||||||
/* How flows are balanced among bond slaves. */
|
/* How flows are balanced among bond member interfaces. */
|
||||||
enum bond_mode {
|
enum bond_mode {
|
||||||
BM_TCP, /* Transport Layer Load Balance. */
|
BM_TCP, /* Transport Layer Load Balance. */
|
||||||
BM_SLB, /* Source Load Balance. */
|
BM_SLB, /* Source Load Balance. */
|
||||||
@ -51,12 +51,12 @@ struct bond_settings {
|
|||||||
const char *primary; /* For AB mode, primary interface name. */
|
const char *primary; /* For AB mode, primary interface name. */
|
||||||
|
|
||||||
/* Link status detection. */
|
/* Link status detection. */
|
||||||
int up_delay; /* ms before enabling an up slave. */
|
int up_delay; /* ms before enabling an up member. */
|
||||||
int down_delay; /* ms before disabling a down slave. */
|
int down_delay; /* ms before disabling a down member. */
|
||||||
|
|
||||||
bool lacp_fallback_ab_cfg; /* Fallback to active-backup on LACP failure. */
|
bool lacp_fallback_ab_cfg; /* Fallback to active-backup on LACP failure. */
|
||||||
|
|
||||||
struct eth_addr active_slave_mac;
|
struct eth_addr active_member_mac;
|
||||||
/* The MAC address of the interface
|
/* The MAC address of the interface
|
||||||
that was active during the last
|
that was active during the last
|
||||||
ovs run. */
|
ovs run. */
|
||||||
@ -74,21 +74,22 @@ void bond_unref(struct bond *);
|
|||||||
struct bond *bond_ref(const struct bond *);
|
struct bond *bond_ref(const struct bond *);
|
||||||
|
|
||||||
bool bond_reconfigure(struct bond *, const struct bond_settings *);
|
bool bond_reconfigure(struct bond *, const struct bond_settings *);
|
||||||
void bond_slave_register(struct bond *, void *slave_, ofp_port_t ofport, struct netdev *);
|
void bond_member_register(struct bond *, void *member_, ofp_port_t ofport,
|
||||||
void bond_slave_set_netdev(struct bond *, void *slave_, struct netdev *);
|
struct netdev *);
|
||||||
void bond_slave_unregister(struct bond *, const void *slave);
|
void bond_member_set_netdev(struct bond *, void *member_, struct netdev *);
|
||||||
|
void bond_member_unregister(struct bond *, const void *member);
|
||||||
|
|
||||||
bool bond_run(struct bond *, enum lacp_status);
|
bool bond_run(struct bond *, enum lacp_status);
|
||||||
void bond_wait(struct bond *);
|
void bond_wait(struct bond *);
|
||||||
|
|
||||||
void bond_slave_set_may_enable(struct bond *, void *slave_, bool may_enable);
|
void bond_member_set_may_enable(struct bond *, void *member_, bool may_enable);
|
||||||
|
|
||||||
/* Special MAC learning support for SLB bonding. */
|
/* Special MAC learning support for SLB bonding. */
|
||||||
bool bond_should_send_learning_packets(struct bond *);
|
bool bond_should_send_learning_packets(struct bond *);
|
||||||
struct dp_packet *bond_compose_learning_packet(struct bond *,
|
struct dp_packet *bond_compose_learning_packet(struct bond *,
|
||||||
const struct eth_addr eth_src,
|
const struct eth_addr eth_src,
|
||||||
uint16_t vlan, void **port_aux);
|
uint16_t vlan, void **port_aux);
|
||||||
bool bond_get_changed_active_slave(const char *name, struct eth_addr *mac,
|
bool bond_get_changed_active_member(const char *name, struct eth_addr *mac,
|
||||||
bool force);
|
bool force);
|
||||||
|
|
||||||
/* Packet processing. */
|
/* Packet processing. */
|
||||||
@ -97,9 +98,9 @@ enum bond_verdict {
|
|||||||
BV_DROP, /* Drop this packet. */
|
BV_DROP, /* Drop this packet. */
|
||||||
BV_DROP_IF_MOVED /* Drop if we've learned a different port. */
|
BV_DROP_IF_MOVED /* Drop if we've learned a different port. */
|
||||||
};
|
};
|
||||||
enum bond_verdict bond_check_admissibility(struct bond *, const void *slave_,
|
enum bond_verdict bond_check_admissibility(struct bond *, const void *member_,
|
||||||
const struct eth_addr dst);
|
const struct eth_addr dst);
|
||||||
void *bond_choose_output_slave(struct bond *, const struct flow *,
|
void *bond_choose_output_member(struct bond *, const struct flow *,
|
||||||
struct flow_wildcards *, uint16_t vlan);
|
struct flow_wildcards *, uint16_t vlan);
|
||||||
|
|
||||||
/* Rebalancing. */
|
/* Rebalancing. */
|
||||||
@ -119,7 +120,7 @@ void bond_rebalance(struct bond *);
|
|||||||
*
|
*
|
||||||
* On handling first output packet, 256 post recirculation flows are installed:
|
* On handling first output packet, 256 post recirculation flows are installed:
|
||||||
*
|
*
|
||||||
* recirc_id=<bond_recirc_id>, dp_hash=<[0..255]>/0xff, actions: output<slave>
|
* recirc_id=<bond_recirc_id>, dp_hash=<[0..255]>/0xff, actions: output<member>
|
||||||
*
|
*
|
||||||
* Bond module pulls stats from those post recirculation rules. If rebalancing
|
* Bond module pulls stats from those post recirculation rules. If rebalancing
|
||||||
* is needed, those rules are updated with new output actions.
|
* is needed, those rules are updated with new output actions.
|
||||||
|
@ -41,8 +41,8 @@ struct rule;
|
|||||||
*
|
*
|
||||||
* Recirculation is the use of freezing to allow a frame to re-enter the
|
* Recirculation is the use of freezing to allow a frame to re-enter the
|
||||||
* datapath packet processing path to achieve more flexible packet processing,
|
* datapath packet processing path to achieve more flexible packet processing,
|
||||||
* such as modifying header fields after MPLS POP action and selecting a slave
|
* such as modifying header fields after MPLS POP action and selecting a
|
||||||
* port for bond ports.
|
* member interface for bond ports.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Data path and user space interface
|
* Data path and user space interface
|
||||||
|
@ -305,7 +305,7 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller,
|
|||||||
SFLEthernet_counters* eth_counters;
|
SFLEthernet_counters* eth_counters;
|
||||||
struct netdev_stats stats;
|
struct netdev_stats stats;
|
||||||
enum netdev_flags flags;
|
enum netdev_flags flags;
|
||||||
struct lacp_slave_stats lacp_stats;
|
struct lacp_member_stats lacp_stats;
|
||||||
const char *ifName;
|
const char *ifName;
|
||||||
|
|
||||||
dsp = dpif_sflow_find_port(ds, u32_to_odp(poller->bridgePort));
|
dsp = dpif_sflow_find_port(ds, u32_to_odp(poller->bridgePort));
|
||||||
|
@ -2431,7 +2431,7 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
|
|||||||
}
|
}
|
||||||
vid = out_xvlan.v[0].vid;
|
vid = out_xvlan.v[0].vid;
|
||||||
if (ovs_list_is_empty(&out_xbundle->xports)) {
|
if (ovs_list_is_empty(&out_xbundle->xports)) {
|
||||||
/* Partially configured bundle with no slaves. Drop the packet. */
|
/* Partially configured bundle with no members. Drop the packet. */
|
||||||
return;
|
return;
|
||||||
} else if (!out_xbundle->bond) {
|
} else if (!out_xbundle->bond) {
|
||||||
xport = CONTAINER_OF(ovs_list_front(&out_xbundle->xports), struct xport,
|
xport = CONTAINER_OF(ovs_list_front(&out_xbundle->xports), struct xport,
|
||||||
@ -2456,12 +2456,12 @@ output_normal(struct xlate_ctx *ctx, const struct xbundle *out_xbundle,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ofport = bond_choose_output_slave(out_xbundle->bond,
|
ofport = bond_choose_output_member(out_xbundle->bond,
|
||||||
&ctx->xin->flow, wc, vid);
|
&ctx->xin->flow, wc, vid);
|
||||||
xport = xport_lookup(ctx->xcfg, ofport);
|
xport = xport_lookup(ctx->xcfg, ofport);
|
||||||
|
|
||||||
if (!xport) {
|
if (!xport) {
|
||||||
/* No slaves enabled, so drop packet. */
|
/* No member interfaces enabled, so drop packet. */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3379,10 +3379,10 @@ process_special(struct xlate_ctx *ctx, const struct xport *xport)
|
|||||||
if (packet) {
|
if (packet) {
|
||||||
lacp_may_enable = lacp_process_packet(xport->xbundle->lacp,
|
lacp_may_enable = lacp_process_packet(xport->xbundle->lacp,
|
||||||
xport->ofport, packet);
|
xport->ofport, packet);
|
||||||
/* Update LACP status in bond-slave to avoid packet-drops until
|
/* Update LACP status in bond-member to avoid packet-drops
|
||||||
* LACP state machine is run by the main thread. */
|
* until LACP state machine is run by the main thread. */
|
||||||
if (xport->xbundle->bond && lacp_may_enable) {
|
if (xport->xbundle->bond && lacp_may_enable) {
|
||||||
bond_slave_set_may_enable(xport->xbundle->bond, xport->ofport,
|
bond_member_set_may_enable(xport->xbundle->bond, xport->ofport,
|
||||||
lacp_may_enable);
|
lacp_may_enable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4210,7 +4210,7 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
|
|||||||
if (xr && bond_use_lb_output_action(xport->xbundle->bond)) {
|
if (xr && bond_use_lb_output_action(xport->xbundle->bond)) {
|
||||||
/*
|
/*
|
||||||
* If bond mode is balance-tcp and optimize balance tcp is enabled
|
* If bond mode is balance-tcp and optimize balance tcp is enabled
|
||||||
* then use the hash directly for slave selection and avoid
|
* then use the hash directly for member selection and avoid
|
||||||
* recirculation.
|
* recirculation.
|
||||||
*
|
*
|
||||||
* Currently support for netdev datapath only.
|
* Currently support for netdev datapath only.
|
||||||
@ -5391,7 +5391,7 @@ xlate_set_queue_action(struct xlate_ctx *ctx, uint32_t queue_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
slave_enabled_cb(ofp_port_t ofp_port, void *xbridge_)
|
member_enabled_cb(ofp_port_t ofp_port, void *xbridge_)
|
||||||
{
|
{
|
||||||
const struct xbridge *xbridge = xbridge_;
|
const struct xbridge *xbridge = xbridge_;
|
||||||
struct xport *port;
|
struct xport *port;
|
||||||
@ -5420,7 +5420,7 @@ xlate_bundle_action(struct xlate_ctx *ctx,
|
|||||||
{
|
{
|
||||||
ofp_port_t port;
|
ofp_port_t port;
|
||||||
|
|
||||||
port = bundle_execute(bundle, &ctx->xin->flow, ctx->wc, slave_enabled_cb,
|
port = bundle_execute(bundle, &ctx->xin->flow, ctx->wc, member_enabled_cb,
|
||||||
CONST_CAST(struct xbridge *, ctx->xbridge));
|
CONST_CAST(struct xbridge *, ctx->xbridge));
|
||||||
if (bundle->dst.field) {
|
if (bundle->dst.field) {
|
||||||
nxm_reg_load(&bundle->dst, ofp_to_u16(port), &ctx->xin->flow, ctx->wc);
|
nxm_reg_load(&bundle->dst, ofp_to_u16(port), &ctx->xin->flow, ctx->wc);
|
||||||
|
@ -2199,7 +2199,7 @@ port_modified(struct ofport *port_)
|
|||||||
struct netdev *netdev = port->up.netdev;
|
struct netdev *netdev = port->up.netdev;
|
||||||
|
|
||||||
if (port->bundle && port->bundle->bond) {
|
if (port->bundle && port->bundle->bond) {
|
||||||
bond_slave_set_netdev(port->bundle->bond, port, netdev);
|
bond_member_set_netdev(port->bundle->bond, port, netdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (port->cfm) {
|
if (port->cfm) {
|
||||||
@ -3140,10 +3140,10 @@ bundle_del_port(struct ofport_dpif *port)
|
|||||||
port->bundle = NULL;
|
port->bundle = NULL;
|
||||||
|
|
||||||
if (bundle->lacp) {
|
if (bundle->lacp) {
|
||||||
lacp_slave_unregister(bundle->lacp, port);
|
lacp_member_unregister(bundle->lacp, port);
|
||||||
}
|
}
|
||||||
if (bundle->bond) {
|
if (bundle->bond) {
|
||||||
bond_slave_unregister(bundle->bond, port);
|
bond_member_unregister(bundle->bond, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle_update(bundle);
|
bundle_update(bundle);
|
||||||
@ -3151,7 +3151,7 @@ bundle_del_port(struct ofport_dpif *port)
|
|||||||
|
|
||||||
static bool
|
static bool
|
||||||
bundle_add_port(struct ofbundle *bundle, ofp_port_t ofp_port,
|
bundle_add_port(struct ofbundle *bundle, ofp_port_t ofp_port,
|
||||||
struct lacp_slave_settings *lacp)
|
struct lacp_member_settings *lacp)
|
||||||
{
|
{
|
||||||
struct ofport_dpif *port;
|
struct ofport_dpif *port;
|
||||||
|
|
||||||
@ -3177,7 +3177,7 @@ bundle_add_port(struct ofbundle *bundle, ofp_port_t ofp_port,
|
|||||||
}
|
}
|
||||||
if (lacp) {
|
if (lacp) {
|
||||||
bundle->ofproto->backer->need_revalidate = REV_RECONFIGURE;
|
bundle->ofproto->backer->need_revalidate = REV_RECONFIGURE;
|
||||||
lacp_slave_register(bundle->lacp, port, lacp);
|
lacp_member_register(bundle->lacp, port, lacp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -3236,8 +3236,8 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ovs_assert(s->n_slaves == 1 || s->bond != NULL);
|
ovs_assert(s->n_members == 1 || s->bond != NULL);
|
||||||
ovs_assert((s->lacp != NULL) == (s->lacp_slaves != NULL));
|
ovs_assert((s->lacp != NULL) == (s->lacp_members != NULL));
|
||||||
|
|
||||||
if (!bundle) {
|
if (!bundle) {
|
||||||
bundle = xmalloc(sizeof *bundle);
|
bundle = xmalloc(sizeof *bundle);
|
||||||
@ -3283,18 +3283,18 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
|||||||
|
|
||||||
/* Update set of ports. */
|
/* Update set of ports. */
|
||||||
ok = true;
|
ok = true;
|
||||||
for (i = 0; i < s->n_slaves; i++) {
|
for (i = 0; i < s->n_members; i++) {
|
||||||
if (!bundle_add_port(bundle, s->slaves[i],
|
if (!bundle_add_port(bundle, s->members[i],
|
||||||
s->lacp ? &s->lacp_slaves[i] : NULL)) {
|
s->lacp ? &s->lacp_members[i] : NULL)) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ok || ovs_list_size(&bundle->ports) != s->n_slaves) {
|
if (!ok || ovs_list_size(&bundle->ports) != s->n_members) {
|
||||||
struct ofport_dpif *next_port;
|
struct ofport_dpif *next_port;
|
||||||
|
|
||||||
LIST_FOR_EACH_SAFE (port, next_port, bundle_node, &bundle->ports) {
|
LIST_FOR_EACH_SAFE (port, next_port, bundle_node, &bundle->ports) {
|
||||||
for (i = 0; i < s->n_slaves; i++) {
|
for (i = 0; i < s->n_members; i++) {
|
||||||
if (s->slaves[i] == port->up.ofp_port) {
|
if (s->members[i] == port->up.ofp_port) {
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3303,7 +3303,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
|||||||
found: ;
|
found: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ovs_assert(ovs_list_size(&bundle->ports) <= s->n_slaves);
|
ovs_assert(ovs_list_size(&bundle->ports) <= s->n_members);
|
||||||
|
|
||||||
if (ovs_list_is_empty(&bundle->ports)) {
|
if (ovs_list_is_empty(&bundle->ports)) {
|
||||||
bundle_destroy(bundle);
|
bundle_destroy(bundle);
|
||||||
@ -3408,7 +3408,7 @@ bundle_set(struct ofproto *ofproto_, void *aux,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
|
LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
|
||||||
bond_slave_register(bundle->bond, port,
|
bond_member_register(bundle->bond, port,
|
||||||
port->up.ofp_port, port->up.netdev);
|
port->up.ofp_port, port->up.netdev);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -3562,7 +3562,7 @@ bundle_run(struct ofbundle *bundle)
|
|||||||
struct ofport_dpif *port;
|
struct ofport_dpif *port;
|
||||||
|
|
||||||
LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
|
LIST_FOR_EACH (port, bundle_node, &bundle->ports) {
|
||||||
bond_slave_set_may_enable(bundle->bond, port, port->up.may_enable);
|
bond_member_set_may_enable(bundle->bond, port, port->up.may_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bond_run(bundle->bond, lacp_status(bundle->lacp))) {
|
if (bond_run(bundle->bond, lacp_status(bundle->lacp))) {
|
||||||
@ -3808,7 +3808,7 @@ may_enable_port(struct ofport_dpif *ofport)
|
|||||||
|
|
||||||
/* If LACP is enabled, it must report that the link is enabled. */
|
/* If LACP is enabled, it must report that the link is enabled. */
|
||||||
if (ofport->bundle
|
if (ofport->bundle
|
||||||
&& !lacp_slave_may_enable(ofport->bundle->lacp, ofport)) {
|
&& !lacp_member_may_enable(ofport->bundle->lacp, ofport)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3824,7 +3824,7 @@ port_run(struct ofport_dpif *ofport)
|
|||||||
|
|
||||||
ofport->carrier_seq = carrier_seq;
|
ofport->carrier_seq = carrier_seq;
|
||||||
if (carrier_changed && ofport->bundle) {
|
if (carrier_changed && ofport->bundle) {
|
||||||
lacp_slave_carrier_changed(ofport->bundle->lacp, ofport, enable);
|
lacp_member_carrier_changed(ofport->bundle->lacp, ofport, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
@ -3936,7 +3936,7 @@ port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
|
|||||||
/* The caller is going to close ofport->up.netdev. If this is a
|
/* The caller is going to close ofport->up.netdev. If this is a
|
||||||
* bonded port, then the bond is using that netdev, so remove it
|
* bonded port, then the bond is using that netdev, so remove it
|
||||||
* from the bond. The client will need to reconfigure everything
|
* from the bond. The client will need to reconfigure everything
|
||||||
* after deleting ports, so then the slave will get re-added. */
|
* after deleting ports, so then the member will get re-added. */
|
||||||
bundle_remove(&ofport->up);
|
bundle_remove(&ofport->up);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4020,11 +4020,12 @@ vport_get_status(const struct ofport *ofport_, char **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
port_get_lacp_stats(const struct ofport *ofport_, struct lacp_slave_stats *stats)
|
port_get_lacp_stats(const struct ofport *ofport_,
|
||||||
|
struct lacp_member_stats *stats)
|
||||||
{
|
{
|
||||||
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
|
struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
|
||||||
if (ofport->bundle && ofport->bundle->lacp) {
|
if (ofport->bundle && ofport->bundle->lacp) {
|
||||||
if (lacp_get_slave_stats(ofport->bundle->lacp, ofport, stats)) {
|
if (lacp_get_member_stats(ofport->bundle->lacp, ofport, stats)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4125,7 +4126,7 @@ port_is_lacp_current(const struct ofport *ofport_)
|
|||||||
{
|
{
|
||||||
const struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
|
const struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
|
||||||
return (ofport->bundle && ofport->bundle->lacp
|
return (ofport->bundle && ofport->bundle->lacp
|
||||||
? lacp_slave_is_current(ofport->bundle->lacp, ofport)
|
? lacp_member_is_current(ofport->bundle->lacp, ofport)
|
||||||
: -1);
|
: -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ int ofproto_dpif_add_internal_flow(struct ofproto_dpif *,
|
|||||||
int ofproto_dpif_delete_internal_flow(struct ofproto_dpif *, struct match *,
|
int ofproto_dpif_delete_internal_flow(struct ofproto_dpif *, struct match *,
|
||||||
int priority);
|
int priority);
|
||||||
int ofproto_dpif_add_lb_output_buckets(struct ofproto_dpif *, uint32_t bond_id,
|
int ofproto_dpif_add_lb_output_buckets(struct ofproto_dpif *, uint32_t bond_id,
|
||||||
const ofp_port_t *slave_map);
|
const ofp_port_t *member_map);
|
||||||
int ofproto_dpif_delete_lb_output_buckets(struct ofproto_dpif *,
|
int ofproto_dpif_delete_lb_output_buckets(struct ofproto_dpif *,
|
||||||
uint32_t bond_id);
|
uint32_t bond_id);
|
||||||
bool ovs_lb_output_action_supported(struct ofproto_dpif *);
|
bool ovs_lb_output_action_supported(struct ofproto_dpif *);
|
||||||
|
@ -1225,7 +1225,7 @@ struct ofproto_class {
|
|||||||
* not support LACP.
|
* not support LACP.
|
||||||
*/
|
*/
|
||||||
int (*port_get_lacp_stats)(const struct ofport *port,
|
int (*port_get_lacp_stats)(const struct ofport *port,
|
||||||
struct lacp_slave_stats *stats);
|
struct lacp_member_stats *stats);
|
||||||
|
|
||||||
/* ## ----------------------- ## */
|
/* ## ----------------------- ## */
|
||||||
/* ## OpenFlow Rule Functions ## */
|
/* ## OpenFlow Rule Functions ## */
|
||||||
@ -1707,11 +1707,11 @@ struct ofproto_class {
|
|||||||
|
|
||||||
/* If 's' is nonnull, this function registers a "bundle" associated with
|
/* If 's' is nonnull, this function registers a "bundle" associated with
|
||||||
* client data pointer 'aux' in 'ofproto'. A bundle is the same concept as
|
* client data pointer 'aux' in 'ofproto'. A bundle is the same concept as
|
||||||
* a Port in OVSDB, that is, it consists of one or more "slave" devices
|
* a Port in OVSDB, that is, it consists of one or more "member"
|
||||||
* (Interfaces, in OVSDB) along with VLAN and LACP configuration and, if
|
* devices (Interfaces, in OVSDB) along with VLAN and LACP configuration
|
||||||
* there is more than one slave, a bonding configuration. If 'aux' is
|
* and, if there is more than one member, a bonding configuration. If 'aux'
|
||||||
* already registered then this function updates its configuration to 's'.
|
* is already registered then this function updates its configuration to
|
||||||
* Otherwise, this function registers a new bundle.
|
* 's'. Otherwise, this function registers a new bundle.
|
||||||
*
|
*
|
||||||
* If 's' is NULL, this function unregisters the bundle registered on
|
* If 's' is NULL, this function unregisters the bundle registered on
|
||||||
* 'ofproto' associated with client data pointer 'aux'. If no such bundle
|
* 'ofproto' associated with client data pointer 'aux'. If no such bundle
|
||||||
|
@ -1391,7 +1391,8 @@ ofproto_port_is_lacp_current(struct ofproto *ofproto, ofp_port_t ofp_port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ofproto_port_get_lacp_stats(const struct ofport *port, struct lacp_slave_stats *stats)
|
ofproto_port_get_lacp_stats(const struct ofport *port,
|
||||||
|
struct lacp_member_stats *stats)
|
||||||
{
|
{
|
||||||
struct ofproto *ofproto = port->ofproto;
|
struct ofproto *ofproto = port->ofproto;
|
||||||
int error;
|
int error;
|
||||||
@ -1409,8 +1410,8 @@ ofproto_port_get_lacp_stats(const struct ofport *port, struct lacp_slave_stats *
|
|||||||
|
|
||||||
/* Registers a "bundle" associated with client data pointer 'aux' in 'ofproto'.
|
/* Registers a "bundle" associated with client data pointer 'aux' in 'ofproto'.
|
||||||
* A bundle is the same concept as a Port in OVSDB, that is, it consists of one
|
* A bundle is the same concept as a Port in OVSDB, that is, it consists of one
|
||||||
* or more "slave" devices (Interfaces, in OVSDB) along with a VLAN
|
* or more "member" devices (Interfaces, in OVSDB) along with a VLAN
|
||||||
* configuration plus, if there is more than one slave, a bonding
|
* configuration plus, if there is more than one member, a bonding
|
||||||
* configuration.
|
* configuration.
|
||||||
*
|
*
|
||||||
* If 'aux' is already registered then this function updates its configuration
|
* If 'aux' is already registered then this function updates its configuration
|
||||||
|
@ -388,7 +388,8 @@ bool ofproto_port_bfd_status_changed(struct ofproto *, ofp_port_t ofp_port);
|
|||||||
int ofproto_port_get_bfd_status(struct ofproto *, ofp_port_t ofp_port,
|
int ofproto_port_get_bfd_status(struct ofproto *, ofp_port_t ofp_port,
|
||||||
struct smap *);
|
struct smap *);
|
||||||
int ofproto_port_is_lacp_current(struct ofproto *, ofp_port_t ofp_port);
|
int ofproto_port_is_lacp_current(struct ofproto *, ofp_port_t ofp_port);
|
||||||
int ofproto_port_get_lacp_stats(const struct ofport *, struct lacp_slave_stats *);
|
int ofproto_port_get_lacp_stats(const struct ofport *,
|
||||||
|
struct lacp_member_stats *);
|
||||||
int ofproto_port_set_stp(struct ofproto *, ofp_port_t ofp_port,
|
int ofproto_port_set_stp(struct ofproto *, ofp_port_t ofp_port,
|
||||||
const struct ofproto_port_stp_settings *);
|
const struct ofproto_port_stp_settings *);
|
||||||
int ofproto_port_get_stp_status(struct ofproto *, ofp_port_t ofp_port,
|
int ofproto_port_get_stp_status(struct ofproto *, ofp_port_t ofp_port,
|
||||||
@ -441,8 +442,8 @@ enum port_priority_tags_mode {
|
|||||||
struct ofproto_bundle_settings {
|
struct ofproto_bundle_settings {
|
||||||
char *name; /* For use in log messages. */
|
char *name; /* For use in log messages. */
|
||||||
|
|
||||||
ofp_port_t *slaves; /* OpenFlow port numbers for slaves. */
|
ofp_port_t *members; /* OpenFlow port numbers for members. */
|
||||||
size_t n_slaves;
|
size_t n_members;
|
||||||
|
|
||||||
enum port_vlan_mode vlan_mode; /* Selects mode for vlan and trunks */
|
enum port_vlan_mode vlan_mode; /* Selects mode for vlan and trunks */
|
||||||
uint16_t qinq_ethtype;
|
uint16_t qinq_ethtype;
|
||||||
@ -452,10 +453,10 @@ struct ofproto_bundle_settings {
|
|||||||
enum port_priority_tags_mode use_priority_tags;
|
enum port_priority_tags_mode use_priority_tags;
|
||||||
/* Use 802.1p tag for frames in VLAN 0? */
|
/* Use 802.1p tag for frames in VLAN 0? */
|
||||||
|
|
||||||
struct bond_settings *bond; /* Must be nonnull iff if n_slaves > 1. */
|
struct bond_settings *bond; /* Must be nonnull iff if n_members > 1. */
|
||||||
|
|
||||||
struct lacp_settings *lacp; /* Nonnull to enable LACP. */
|
struct lacp_settings *lacp; /* Nonnull to enable LACP. */
|
||||||
struct lacp_slave_settings *lacp_slaves; /* Array of n_slaves elements. */
|
struct lacp_member_settings *lacp_members; /* Array of n_members elements. */
|
||||||
|
|
||||||
bool protected; /* Protected port mode */
|
bool protected; /* Protected port mode */
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@ AT_BANNER([bundle link selection])
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle link selection])
|
AT_SETUP([hrw bundle link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,hrw,ofport,NXM_NX_REG0[],slaves:1,2,3,4,5']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,hrw,ofport,NXM_NX_REG0[],members:1,2,3,4,5']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
# 100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
# 100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
||||||
# 110000: disruption=0.50 (perfect=0.50) 0.50 0.50 0.00 0.00 0.00 0.00
|
# 110000: disruption=0.50 (perfect=0.50) 0.50 0.50 0.00 0.00 0.00 0.00
|
||||||
@ -80,7 +80,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([active_backup bundle link selection])
|
AT_SETUP([active_backup bundle link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,active_backup,ofport,NXM_NX_REG0[],slaves:1,2,3,4,5,6']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,active_backup,ofport,NXM_NX_REG0[],members:1,2,3,4,5,6']],
|
||||||
[0],
|
[0],
|
||||||
[100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
[100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
||||||
110000: disruption=0.00 (perfect=0.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
110000: disruption=0.00 (perfect=0.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
||||||
@ -152,7 +152,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle single link selection])
|
AT_SETUP([hrw bundle single link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,hrw,ofport,NXM_NX_REG0[],slaves:1']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,hrw,ofport,NXM_NX_REG0[],members:1']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
# 1: disruption=1.00 (perfect=1.00) 1.00
|
# 1: disruption=1.00 (perfect=1.00) 1.00
|
||||||
# 0: disruption=1.00 (perfect=1.00) 0.00
|
# 0: disruption=1.00 (perfect=1.00) 0.00
|
||||||
@ -161,7 +161,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle no link selection])
|
AT_SETUP([hrw bundle no link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,hrw,ofport,NXM_NX_REG0[],slaves:']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l4,60,hrw,ofport,NXM_NX_REG0[],members:']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
#: disruption=0.00 (perfect=0.00)
|
#: disruption=0.00 (perfect=0.00)
|
||||||
@ -176,29 +176,29 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([bundle action bad fields])
|
AT_SETUP([bundle action bad fields])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(xyzzy,60,hrw,ofport,slaves:1,2))'], [1], [],
|
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(xyzzy,60,hrw,ofport,members:1,2))'], [1], [],
|
||||||
[ovs-ofctl: xyzzy,60,hrw,ofport,slaves:1,2: unknown fields `xyzzy'
|
[ovs-ofctl: xyzzy,60,hrw,ofport,members:1,2: unknown fields `xyzzy'
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([bundle action bad algorithm])
|
AT_SETUP([bundle action bad algorithm])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(symmetric_l4,60,fubar,ofport,slaves:1,2))'], [1], [],
|
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(symmetric_l4,60,fubar,ofport,members:1,2))'], [1], [],
|
||||||
[ovs-ofctl: symmetric_l4,60,fubar,ofport,slaves:1,2: unknown algorithm `fubar'
|
[ovs-ofctl: symmetric_l4,60,fubar,ofport,members:1,2: unknown algorithm `fubar'
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([bundle action bad slave type])
|
AT_SETUP([bundle action bad member type])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(symmetric_l4,60,hrw,robot,slaves:1,2))'], [1], [],
|
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(symmetric_l4,60,hrw,robot,members:1,2))'], [1], [],
|
||||||
[ovs-ofctl: symmetric_l4,60,hrw,robot,slaves:1,2: unknown slave_type `robot'
|
[ovs-ofctl: symmetric_l4,60,hrw,robot,members:1,2: unknown member_type `robot'
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([bundle action bad slave delimiter])
|
AT_SETUP([bundle action bad member delimiter])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(symmetric_l4,60,hrw,ofport,robot:1,2))'], [1], [],
|
AT_CHECK([ovs-ofctl parse-flow 'actions=bundle(symmetric_l4,60,hrw,ofport,robot:1,2))'], [1], [],
|
||||||
[ovs-ofctl: symmetric_l4,60,hrw,ofport,robot:1,2: missing slave delimiter, expected `slaves' got `robot'
|
[ovs-ofctl: symmetric_l4,60,hrw,ofport,robot:1,2: missing member delimiter, expected `members', got `robot'
|
||||||
])
|
])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
@ -211,9 +211,9 @@ dnl Valgrind warnings for use-after-free bugs.
|
|||||||
AT_SETUP([bundle action with many ports])
|
AT_SETUP([bundle action with many ports])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
OVS_VSWITCHD_START
|
OVS_VSWITCHD_START
|
||||||
AT_CHECK([ovs-ofctl add-flow br0 'actions=set_field:0x1->metadata,set_field:0x2->metadata,set_field:0x3->metadata,set_field:0x4->metadata,bundle(symmetric_l4,0,hrw,ofport,slaves:[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]])'])
|
AT_CHECK([ovs-ofctl add-flow br0 'actions=set_field:0x1->metadata,set_field:0x2->metadata,set_field:0x3->metadata,set_field:0x4->metadata,bundle(symmetric_l4,0,hrw,ofport,members:[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]])'])
|
||||||
AT_CHECK([ovs-ofctl dump-flows br0 --no-stats], [0], [dnl
|
AT_CHECK([ovs-ofctl dump-flows br0 --no-stats], [0], [dnl
|
||||||
actions=load:0x1->OXM_OF_METADATA[[]],load:0x2->OXM_OF_METADATA[[]],load:0x3->OXM_OF_METADATA[[]],load:0x4->OXM_OF_METADATA[[]],bundle(symmetric_l4,0,hrw,ofport,slaves:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)
|
actions=load:0x1->OXM_OF_METADATA[[]],load:0x2->OXM_OF_METADATA[[]],load:0x3->OXM_OF_METADATA[[]],load:0x4->OXM_OF_METADATA[[]],bundle(symmetric_l4,0,hrw,ofport,members:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)
|
||||||
])
|
])
|
||||||
OVS_VSWITCHD_STOP
|
OVS_VSWITCHD_STOP
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
@ -226,7 +226,7 @@ OVS_VSWITCHD_START([dnl
|
|||||||
add-port br0 p2 -- set Interface p2 type=dummy -- \
|
add-port br0 p2 -- set Interface p2 type=dummy -- \
|
||||||
set Interface p2 ofport_request=2
|
set Interface p2 ofport_request=2
|
||||||
])
|
])
|
||||||
AT_CHECK([ovs-ofctl add-flow br0 'actions=bundle(eth_src,50,active_backup,ofport,slaves:1,2)'])
|
AT_CHECK([ovs-ofctl add-flow br0 'actions=bundle(eth_src,50,active_backup,ofport,members:1,2)'])
|
||||||
AT_CHECK([ovs-ofctl mod-port br0 p1 up])
|
AT_CHECK([ovs-ofctl mod-port br0 p1 up])
|
||||||
AT_CHECK([ovs-ofctl mod-port br0 p2 up])
|
AT_CHECK([ovs-ofctl mod-port br0 p2 up])
|
||||||
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=LOCAL,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06'], [0], [stdout])
|
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=LOCAL,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06'], [0], [stdout])
|
||||||
@ -264,7 +264,7 @@ OVS_VSWITCHD_START([dnl
|
|||||||
add-port br0 p2 -- set Interface p2 type=dummy -- \
|
add-port br0 p2 -- set Interface p2 type=dummy -- \
|
||||||
set Interface p2 ofport_request=2
|
set Interface p2 ofport_request=2
|
||||||
])
|
])
|
||||||
AT_CHECK([ovs-ofctl add-flow br0 'actions=bundle_load(eth_src,50,hrw,ofport,OXM_OF_ETH_SRC[[0..15]],slaves:1,2)'])
|
AT_CHECK([ovs-ofctl add-flow br0 'actions=bundle_load(eth_src,50,hrw,ofport,OXM_OF_ETH_SRC[[0..15]],members:1,2)'])
|
||||||
AT_CHECK([ovs-ofctl mod-port br0 p1 down])
|
AT_CHECK([ovs-ofctl mod-port br0 p1 down])
|
||||||
AT_CHECK([ovs-ofctl mod-port br0 p2 down])
|
AT_CHECK([ovs-ofctl mod-port br0 p2 down])
|
||||||
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=LOCAL,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06'], [0], [stdout])
|
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=LOCAL,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:06'], [0], [stdout])
|
||||||
@ -276,7 +276,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle symmetric_l3 link selection])
|
AT_SETUP([hrw bundle symmetric_l3 link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],slaves:1,2,3,4,5']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],members:1,2,3,4,5']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
# 100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
# 100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
||||||
# 110000: disruption=0.50 (perfect=0.50) 0.50 0.50 0.00 0.00 0.00 0.00
|
# 110000: disruption=0.50 (perfect=0.50) 0.50 0.50 0.00 0.00 0.00 0.00
|
||||||
@ -347,7 +347,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([active_backup bundle symmetric_l3 link selection])
|
AT_SETUP([active_backup bundle symmetric_l3 link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,active_backup,ofport,NXM_NX_REG0[],slaves:1,2,3,4,5,6']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,active_backup,ofport,NXM_NX_REG0[],members:1,2,3,4,5,6']],
|
||||||
[0],
|
[0],
|
||||||
[100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
[100000: disruption=1.00 (perfect=1.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
||||||
110000: disruption=0.00 (perfect=0.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
110000: disruption=0.00 (perfect=0.00) 1.00 0.00 0.00 0.00 0.00 0.00
|
||||||
@ -419,7 +419,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle symmetric_l3 single link selection])
|
AT_SETUP([hrw bundle symmetric_l3 single link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],slaves:1']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],members:1']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
# 1: disruption=1.00 (perfect=1.00) 1.00
|
# 1: disruption=1.00 (perfect=1.00) 1.00
|
||||||
# 0: disruption=1.00 (perfect=1.00) 0.00
|
# 0: disruption=1.00 (perfect=1.00) 0.00
|
||||||
@ -428,7 +428,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle symmetric_l3 single link selection])
|
AT_SETUP([hrw bundle symmetric_l3 single link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],slaves:1']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],members:1']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
# 1: disruption=1.00 (perfect=1.00) 1.00
|
# 1: disruption=1.00 (perfect=1.00) 1.00
|
||||||
# 0: disruption=1.00 (perfect=1.00) 0.00
|
# 0: disruption=1.00 (perfect=1.00) 0.00
|
||||||
@ -437,7 +437,7 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([hrw bundle symmetric_l3 no link selection])
|
AT_SETUP([hrw bundle symmetric_l3 no link selection])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],slaves:']],
|
AT_CHECK([[ovstest test-bundle 'symmetric_l3,60,hrw,ofport,NXM_NX_REG0[],members:']],
|
||||||
[0], [ignore])
|
[0], [ignore])
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
#: disruption=0.00 (perfect=0.00)
|
#: disruption=0.00 (perfect=0.00)
|
||||||
@ -446,9 +446,9 @@ AT_CLEANUP
|
|||||||
AT_SETUP([bundle symmetric_l3 action with many ports])
|
AT_SETUP([bundle symmetric_l3 action with many ports])
|
||||||
AT_KEYWORDS([bundle_action])
|
AT_KEYWORDS([bundle_action])
|
||||||
OVS_VSWITCHD_START
|
OVS_VSWITCHD_START
|
||||||
AT_CHECK([ovs-ofctl add-flow br0 'actions=set_field:0x1->metadata,set_field:0x2->metadata,set_field:0x3->metadata,set_field:0x4->metadata,bundle(symmetric_l3,0,hrw,ofport,slaves:[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]])'])
|
AT_CHECK([ovs-ofctl add-flow br0 'actions=set_field:0x1->metadata,set_field:0x2->metadata,set_field:0x3->metadata,set_field:0x4->metadata,bundle(symmetric_l3,0,hrw,ofport,members:[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]])'])
|
||||||
AT_CHECK([ovs-ofctl dump-flows br0 --no-stats], [0], [dnl
|
AT_CHECK([ovs-ofctl dump-flows br0 --no-stats], [0], [dnl
|
||||||
actions=load:0x1->OXM_OF_METADATA[[]],load:0x2->OXM_OF_METADATA[[]],load:0x3->OXM_OF_METADATA[[]],load:0x4->OXM_OF_METADATA[[]],bundle(symmetric_l3,0,hrw,ofport,slaves:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)
|
actions=load:0x1->OXM_OF_METADATA[[]],load:0x2->OXM_OF_METADATA[[]],load:0x3->OXM_OF_METADATA[[]],load:0x4->OXM_OF_METADATA[[]],bundle(symmetric_l3,0,hrw,ofport,members:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40)
|
||||||
])
|
])
|
||||||
OVS_VSWITCHD_STOP
|
OVS_VSWITCHD_STOP
|
||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
146
tests/lacp.at
146
tests/lacp.at
@ -5,9 +5,9 @@ m4_define([STRIP_RECIRC_ID], [[sed '
|
|||||||
s/Recirc-ID.*$/<del>/
|
s/Recirc-ID.*$/<del>/
|
||||||
' ]])
|
' ]])
|
||||||
|
|
||||||
# Strips out active slave mac address since it may change over time.
|
# Strips out active member mac address since it may change over time.
|
||||||
m4_define([STRIP_ACTIVE_SLAVE_MAC], [[sed '
|
m4_define([STRIP_ACTIVE_MEMBER_MAC], [[sed '
|
||||||
s/active slave mac.*$/<active slave mac del>/
|
s/active member mac.*$/<active member mac del>/
|
||||||
' ]])
|
' ]])
|
||||||
|
|
||||||
AT_SETUP([lacp - config])
|
AT_SETUP([lacp - config])
|
||||||
@ -27,7 +27,7 @@ AT_CHECK([ovs-appctl lacp/show], [0], [dnl
|
|||||||
aggregation key: 1
|
aggregation key: 1
|
||||||
lacp_time: slow
|
lacp_time: slow
|
||||||
|
|
||||||
slave: p1: expired attached
|
member: p1: expired attached
|
||||||
port_id: 1
|
port_id: 1
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -78,7 +78,7 @@ AT_CHECK([sed -e 's/aggregation key:.*/aggregation key: <omitted>/' < stdout], [
|
|||||||
aggregation key: <omitted>
|
aggregation key: <omitted>
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p1: expired attached
|
member: p1: expired attached
|
||||||
port_id: 11
|
port_id: 11
|
||||||
port_priority: 111
|
port_priority: 111
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -97,7 +97,7 @@ slave: p1: expired attached
|
|||||||
partner key: 0
|
partner key: 0
|
||||||
partner state: timeout
|
partner state: timeout
|
||||||
|
|
||||||
slave: p2: expired attached
|
member: p2: expired attached
|
||||||
port_id: 22
|
port_id: 22
|
||||||
port_priority: 222
|
port_priority: 222
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -127,12 +127,12 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
active slave mac: 00:00:00:00:00:00(none)
|
active member mac: 00:00:00:00:00:00(none)
|
||||||
|
|
||||||
slave p1: disabled
|
member p1: disabled
|
||||||
may_enable: false
|
may_enable: false
|
||||||
|
|
||||||
slave p2: disabled
|
member p2: disabled
|
||||||
may_enable: false
|
may_enable: false
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -140,8 +140,8 @@ OVS_VSWITCHD_STOP
|
|||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([lacp - negotiation])
|
AT_SETUP([lacp - negotiation])
|
||||||
# Create bond0 on br0 with interfaces p0 and p1
|
# Create bond0 on br0 with members p0 and p1
|
||||||
# and bond1 on br1 with interfaces p2 and p3
|
# and bond1 on br1 with members p2 and p3
|
||||||
# with p0 patched to p2 and p1 patched to p3.
|
# with p0 patched to p2 and p1 patched to p3.
|
||||||
OVS_VSWITCHD_START(
|
OVS_VSWITCHD_START(
|
||||||
[add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
[add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
||||||
@ -193,9 +193,9 @@ done
|
|||||||
AT_CHECK(
|
AT_CHECK(
|
||||||
[ovs-appctl lacp/show bond0
|
[ovs-appctl lacp/show bond0
|
||||||
ovs-appctl lacp/show bond1
|
ovs-appctl lacp/show bond1
|
||||||
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC
|
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
|
||||||
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [stdout])
|
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [stdout])
|
||||||
AT_CHECK([sed '/active slave/d' stdout], [0], [dnl
|
AT_CHECK([sed '/active member/d' stdout], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
status: active negotiated
|
status: active negotiated
|
||||||
sys_id: aa:55:aa:55:00:00
|
sys_id: aa:55:aa:55:00:00
|
||||||
@ -203,7 +203,7 @@ AT_CHECK([sed '/active slave/d' stdout], [0], [dnl
|
|||||||
aggregation key: 2
|
aggregation key: 2
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p0: current attached
|
member: p0: current attached
|
||||||
port_id: 1
|
port_id: 1
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -222,7 +222,7 @@ slave: p0: current attached
|
|||||||
partner key: 4
|
partner key: 4
|
||||||
partner state: activity timeout aggregation synchronized collecting distributing
|
partner state: activity timeout aggregation synchronized collecting distributing
|
||||||
|
|
||||||
slave: p1: current attached
|
member: p1: current attached
|
||||||
port_id: 2
|
port_id: 2
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -247,7 +247,7 @@ slave: p1: current attached
|
|||||||
aggregation key: 4
|
aggregation key: 4
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p2: current attached
|
member: p2: current attached
|
||||||
port_id: 3
|
port_id: 3
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -266,7 +266,7 @@ slave: p2: current attached
|
|||||||
partner key: 2
|
partner key: 2
|
||||||
partner state: activity timeout aggregation synchronized collecting distributing
|
partner state: activity timeout aggregation synchronized collecting distributing
|
||||||
|
|
||||||
slave: p3: current attached
|
member: p3: current attached
|
||||||
port_id: 4
|
port_id: 4
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -295,10 +295,10 @@ lacp_status: negotiated
|
|||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
|
|
||||||
slave p0: enabled
|
member p0: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
---- bond1 ----
|
---- bond1 ----
|
||||||
@ -312,16 +312,16 @@ lacp_status: negotiated
|
|||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
AT_CHECK([grep 'active slave$' stdout], [0], [dnl
|
AT_CHECK([grep 'active member$' stdout], [0], [dnl
|
||||||
active slave
|
active member
|
||||||
active slave
|
active member
|
||||||
])
|
])
|
||||||
|
|
||||||
# Redirect the patch link between p0 and p2 so that no packets get
|
# Redirect the patch link between p0 and p2 so that no packets get
|
||||||
@ -335,8 +335,8 @@ ovs-appctl time/warp 4100 100
|
|||||||
AT_CHECK(
|
AT_CHECK(
|
||||||
[ovs-appctl lacp/show bond0
|
[ovs-appctl lacp/show bond0
|
||||||
ovs-appctl lacp/show bond1
|
ovs-appctl lacp/show bond1
|
||||||
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC
|
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
|
||||||
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [dnl
|
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
status: active negotiated
|
status: active negotiated
|
||||||
sys_id: aa:55:aa:55:00:00
|
sys_id: aa:55:aa:55:00:00
|
||||||
@ -344,7 +344,7 @@ ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [d
|
|||||||
aggregation key: 2
|
aggregation key: 2
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p0: expired attached
|
member: p0: expired attached
|
||||||
port_id: 1
|
port_id: 1
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -363,7 +363,7 @@ slave: p0: expired attached
|
|||||||
partner key: 4
|
partner key: 4
|
||||||
partner state: activity timeout aggregation collecting distributing
|
partner state: activity timeout aggregation collecting distributing
|
||||||
|
|
||||||
slave: p1: current attached
|
member: p1: current attached
|
||||||
port_id: 2
|
port_id: 2
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -388,7 +388,7 @@ slave: p1: current attached
|
|||||||
aggregation key: 4
|
aggregation key: 4
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p2: expired attached
|
member: p2: expired attached
|
||||||
port_id: 3
|
port_id: 3
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -407,7 +407,7 @@ slave: p2: expired attached
|
|||||||
partner key: 2
|
partner key: 2
|
||||||
partner state: activity timeout aggregation collecting distributing
|
partner state: activity timeout aggregation collecting distributing
|
||||||
|
|
||||||
slave: p3: current attached
|
member: p3: current attached
|
||||||
port_id: 4
|
port_id: 4
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -435,13 +435,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p0: disabled
|
member p0: disabled
|
||||||
may_enable: false
|
may_enable: false
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
---- bond1 ----
|
---- bond1 ----
|
||||||
@ -454,13 +454,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p2: disabled
|
member p2: disabled
|
||||||
may_enable: false
|
may_enable: false
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -471,8 +471,8 @@ ovs-appctl time/warp 4100 100
|
|||||||
AT_CHECK(
|
AT_CHECK(
|
||||||
[ovs-appctl lacp/show bond0
|
[ovs-appctl lacp/show bond0
|
||||||
ovs-appctl lacp/show bond1
|
ovs-appctl lacp/show bond1
|
||||||
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC
|
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
|
||||||
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [dnl
|
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
status: active negotiated
|
status: active negotiated
|
||||||
sys_id: aa:55:aa:55:00:00
|
sys_id: aa:55:aa:55:00:00
|
||||||
@ -480,7 +480,7 @@ ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [d
|
|||||||
aggregation key: 2
|
aggregation key: 2
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p0: defaulted detached
|
member: p0: defaulted detached
|
||||||
port_id: 1
|
port_id: 1
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -499,7 +499,7 @@ slave: p0: defaulted detached
|
|||||||
partner key: 0
|
partner key: 0
|
||||||
partner state:
|
partner state:
|
||||||
|
|
||||||
slave: p1: current attached
|
member: p1: current attached
|
||||||
port_id: 2
|
port_id: 2
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -524,7 +524,7 @@ slave: p1: current attached
|
|||||||
aggregation key: 4
|
aggregation key: 4
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p2: defaulted detached
|
member: p2: defaulted detached
|
||||||
port_id: 3
|
port_id: 3
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: false
|
may_enable: false
|
||||||
@ -543,7 +543,7 @@ slave: p2: defaulted detached
|
|||||||
partner key: 0
|
partner key: 0
|
||||||
partner state:
|
partner state:
|
||||||
|
|
||||||
slave: p3: current attached
|
member: p3: current attached
|
||||||
port_id: 4
|
port_id: 4
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -571,13 +571,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p0: disabled
|
member p0: disabled
|
||||||
may_enable: false
|
may_enable: false
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
---- bond1 ----
|
---- bond1 ----
|
||||||
@ -590,13 +590,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p2: disabled
|
member p2: disabled
|
||||||
may_enable: false
|
may_enable: false
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -612,8 +612,8 @@ ovs-appctl time/warp 30100 100
|
|||||||
AT_CHECK(
|
AT_CHECK(
|
||||||
[ovs-appctl lacp/show bond0
|
[ovs-appctl lacp/show bond0
|
||||||
ovs-appctl lacp/show bond1
|
ovs-appctl lacp/show bond1
|
||||||
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC
|
ovs-appctl bond/show bond0 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC
|
||||||
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [dnl
|
ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC ], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
status: active negotiated
|
status: active negotiated
|
||||||
sys_id: aa:55:aa:55:00:00
|
sys_id: aa:55:aa:55:00:00
|
||||||
@ -621,7 +621,7 @@ ovs-appctl bond/show bond1 | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC ], [0], [d
|
|||||||
aggregation key: 2
|
aggregation key: 2
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p0: current attached
|
member: p0: current attached
|
||||||
port_id: 1
|
port_id: 1
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -640,7 +640,7 @@ slave: p0: current attached
|
|||||||
partner key: 4
|
partner key: 4
|
||||||
partner state: activity timeout aggregation synchronized collecting distributing
|
partner state: activity timeout aggregation synchronized collecting distributing
|
||||||
|
|
||||||
slave: p1: current attached
|
member: p1: current attached
|
||||||
port_id: 2
|
port_id: 2
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -665,7 +665,7 @@ slave: p1: current attached
|
|||||||
aggregation key: 4
|
aggregation key: 4
|
||||||
lacp_time: fast
|
lacp_time: fast
|
||||||
|
|
||||||
slave: p2: current attached
|
member: p2: current attached
|
||||||
port_id: 3
|
port_id: 3
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -684,7 +684,7 @@ slave: p2: current attached
|
|||||||
partner key: 2
|
partner key: 2
|
||||||
partner state: activity timeout aggregation synchronized collecting distributing
|
partner state: activity timeout aggregation synchronized collecting distributing
|
||||||
|
|
||||||
slave: p3: current attached
|
member: p3: current attached
|
||||||
port_id: 4
|
port_id: 4
|
||||||
port_priority: 65535
|
port_priority: 65535
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -712,13 +712,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p0: enabled
|
member p0: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
---- bond1 ----
|
---- bond1 ----
|
||||||
@ -731,13 +731,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: negotiated
|
lacp_status: negotiated
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -771,8 +771,8 @@ 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.
|
# Set miss_send_len to 128, enabling port_status messages to our service connection.
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080
|
ovs-appctl -t ovs-ofctl ofctl/send 0409000c0123456700000080
|
||||||
|
|
||||||
# Create bond0 on br0 with interfaces p0 and p1
|
# Create bond0 on br0 with members p0 and p1
|
||||||
# and bond1 on br1 with interfaces p2 and p3
|
# and bond1 on br1 with members p2 and p3
|
||||||
# with p0 patched to p2 and p1 patched to 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 \
|
AT_CHECK([ovs-vsctl add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
||||||
other-config:lacp-time=fast \
|
other-config:lacp-time=fast \
|
||||||
@ -866,8 +866,8 @@ 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.
|
# Set miss_send_len to 128, enabling port_status messages to our service connection.
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send 0509000c0123456700000080
|
ovs-appctl -t ovs-ofctl ofctl/send 0509000c0123456700000080
|
||||||
|
|
||||||
# Create bond0 on br0 with interfaces p0 and p1
|
# Create bond0 on br0 with members p0 and p1
|
||||||
# and bond1 on br1 with interfaces p2 and p3
|
# and bond1 on br1 with members p2 and p3
|
||||||
# with p0 patched to p2 and p1 patched to 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 \
|
AT_CHECK([ovs-vsctl add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
||||||
other-config:lacp-time=fast \
|
other-config:lacp-time=fast \
|
||||||
@ -961,8 +961,8 @@ 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.
|
# Set miss_send_len to 128, enabling port_status messages to our service connection.
|
||||||
ovs-appctl -t ovs-ofctl ofctl/send 0609000c0123456700000080
|
ovs-appctl -t ovs-ofctl ofctl/send 0609000c0123456700000080
|
||||||
|
|
||||||
# Create bond0 on br0 with interfaces p0 and p1
|
# Create bond0 on br0 with members p0 and p1
|
||||||
# and bond1 on br1 with interfaces p2 and p3
|
# and bond1 on br1 with members p2 and p3
|
||||||
# with p0 patched to p2 and p1 patched to 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 \
|
AT_CHECK([ovs-vsctl add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
||||||
other-config:lacp-time=fast \
|
other-config:lacp-time=fast \
|
||||||
|
@ -80,11 +80,11 @@ ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffff0000ffff0000
|
|||||||
# actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[])
|
# actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[])
|
||||||
ffff 0020 00002320 000a 0000 0032 0000 0000 0000 0000 0000 0000 001f 00010004
|
ffff 0020 00002320 000a 0000 0032 0000 0000 0000 0000 0000 0000 001f 00010004
|
||||||
|
|
||||||
# actions=bundle(eth_src,0,hrw,ofport,slaves:4,8)
|
# actions=bundle(eth_src,0,hrw,ofport,members:4,8)
|
||||||
ffff 0028 00002320 000c 0001 0000 0000 00000002 0002 0000 00000000 00000000 dnl
|
ffff 0028 00002320 000c 0001 0000 0000 00000002 0002 0000 00000000 00000000 dnl
|
||||||
0004 0008 00000000
|
0004 0008 00000000
|
||||||
|
|
||||||
# actions=bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[],slaves:4,8)
|
# actions=bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[],members:4,8)
|
||||||
ffff 0028 00002320 000d 0001 0000 0000 00000002 0002 001f 00010004 00000000 dnl
|
ffff 0028 00002320 000d 0001 0000 0000 00000002 0002 001f 00010004 00000000 dnl
|
||||||
0004 0008 00000000
|
0004 0008 00000000
|
||||||
|
|
||||||
@ -444,11 +444,11 @@ ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff
|
|||||||
# actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[])
|
# actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[])
|
||||||
ffff 0020 00002320 000a 0000 0032 0000 0000 0000 0000 0000 0000 001f 00010004
|
ffff 0020 00002320 000a 0000 0032 0000 0000 0000 0000 0000 0000 001f 00010004
|
||||||
|
|
||||||
# actions=bundle(eth_src,0,hrw,ofport,slaves:4,8)
|
# actions=bundle(eth_src,0,hrw,ofport,members:4,8)
|
||||||
ffff 0028 00002320 000c 0001 0000 0000 00000002 0002 0000 00000000 00000000 dnl
|
ffff 0028 00002320 000c 0001 0000 0000 00000002 0002 0000 00000000 00000000 dnl
|
||||||
0004 0008 00000000
|
0004 0008 00000000
|
||||||
|
|
||||||
# actions=bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[],slaves:4,8)
|
# actions=bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[],members:4,8)
|
||||||
ffff 0028 00002320 000d 0001 0000 0000 00000002 0002 001f 00010004 00000000 dnl
|
ffff 0028 00002320 000d 0001 0000 0000 00000002 0002 001f 00010004 00000000 dnl
|
||||||
0004 0008 00000000
|
0004 0008 00000000
|
||||||
|
|
||||||
@ -958,17 +958,17 @@ bad_action 'enqueue:asdf:123' 'asdf: enqueue to unknown port'
|
|||||||
# bundle
|
# bundle
|
||||||
bad_action 'bundle:123' '123: not enough arguments to bundle action'
|
bad_action 'bundle:123' '123: not enough arguments to bundle action'
|
||||||
bad_action 'bundle(symmetric_l4,60,hrw,ofport,ports:1,2,3,4,5)' \
|
bad_action 'bundle(symmetric_l4,60,hrw,ofport,ports:1,2,3,4,5)' \
|
||||||
"symmetric_l4,60,hrw,ofport,ports:1,2,3,4,5: missing slave delimiter, expected \`slaves' got \`ports'"
|
"symmetric_l4,60,hrw,ofport,ports:1,2,3,4,5: missing member delimiter, expected \`members', got \`ports'"
|
||||||
bad_action 'bundle(symmetric_l4,60,hrw,ofport,slaves:xyzzy,2,3,4,5)' \
|
bad_action 'bundle(symmetric_l4,60,hrw,ofport,members:xyzzy,2,3,4,5)' \
|
||||||
'xyzzy: bad port number'
|
'xyzzy: bad port number'
|
||||||
bad_action 'bundle(asymmetric_l4,60,hrw,ofport,slaves:1,2,3,4,5)' \
|
bad_action 'bundle(asymmetric_l4,60,hrw,ofport,members:1,2,3,4,5)' \
|
||||||
"asymmetric_l4,60,hrw,ofport,slaves:1,2,3,4,5: unknown fields \`asymmetric_l4'"
|
"asymmetric_l4,60,hrw,ofport,members:1,2,3,4,5: unknown fields \`asymmetric_l4'"
|
||||||
bad_action 'bundle(symmetric_l4,60,hrt,ofport,slaves:1,2,3,4,5)' \
|
bad_action 'bundle(symmetric_l4,60,hrt,ofport,members:1,2,3,4,5)' \
|
||||||
"symmetric_l4,60,hrt,ofport,slaves:1,2,3,4,5: unknown algorithm \`hrt'"
|
"symmetric_l4,60,hrt,ofport,members:1,2,3,4,5: unknown algorithm \`hrt'"
|
||||||
bad_action 'bundle(symmetric_l4,60,hrw,odpport,slaves:1,2,3,4,5)' \
|
bad_action 'bundle(symmetric_l4,60,hrw,odpport,members:1,2,3,4,5)' \
|
||||||
"symmetric_l4,60,hrw,odpport,slaves:1,2,3,4,5: unknown slave_type \`odpport'"
|
"symmetric_l4,60,hrw,odpport,members:1,2,3,4,5: unknown member_type \`odpport'"
|
||||||
bad_action 'bundle_load(symmetric_l4,60,hrw,ofport,actset_output,slaves:1,2,3,4,5)' \
|
bad_action 'bundle_load(symmetric_l4,60,hrw,ofport,actset_output,members:1,2,3,4,5)' \
|
||||||
"symmetric_l4,60,hrw,ofport,actset_output,slaves:1,2,3,4,5: experimenter OXM field 'actset_output' not supported"
|
"symmetric_l4,60,hrw,ofport,actset_output,members:1,2,3,4,5: experimenter OXM field 'actset_output' not supported"
|
||||||
|
|
||||||
# mod_vlan_vid
|
# mod_vlan_vid
|
||||||
bad_action 'mod_vlan_vid:6000' '6000: not a valid VLAN VID'
|
bad_action 'mod_vlan_vid:6000' '6000: not a valid VLAN VID'
|
||||||
|
@ -31,8 +31,8 @@ AT_CLEANUP
|
|||||||
|
|
||||||
AT_SETUP([ofproto-dpif - active-backup bonding (with primary)])
|
AT_SETUP([ofproto-dpif - active-backup bonding (with primary)])
|
||||||
|
|
||||||
dnl Create br0 with interfaces p1, p2 and p7, creating bond0 with p1 and
|
dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and
|
||||||
dnl p2 (p1 as primary) and br1 with interfaces p3, p4 and p8.
|
dnl p2 (p1 as primary) and br1 with members p3, p4 and p8.
|
||||||
dnl toggle p1,p2 of bond0 up and down to test bonding in active-backup mode.
|
dnl toggle p1,p2 of bond0 up and down to test bonding in active-backup mode.
|
||||||
dnl With p1 down and p2 up/active, bring p1 back up. Since p1 is the primary,
|
dnl With p1 down and p2 up/active, bring p1 back up. Since p1 is the primary,
|
||||||
dnl it should become active.
|
dnl it should become active.
|
||||||
@ -81,7 +81,7 @@ recirc_id(0),in_port(4),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=ff:
|
|||||||
|
|
||||||
ovs-appctl netdev-dummy/set-admin-state p1 up
|
ovs-appctl netdev-dummy/set-admin-state p1 up
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC], [0], [dnl
|
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
bond_mode: active-backup
|
bond_mode: active-backup
|
||||||
bond may use recirculation: no, <del>
|
bond may use recirculation: no, <del>
|
||||||
@ -91,13 +91,13 @@ downdelay: 0 ms
|
|||||||
lacp_status: off
|
lacp_status: off
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: p1
|
active-backup primary: p1
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -118,18 +118,18 @@ OVS_VSWITCHD_START(
|
|||||||
add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy --])
|
add-port br0 p7 -- set interface p7 ofport_request=7 type=dummy --])
|
||||||
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
|
AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
|
||||||
|
|
||||||
dnl Make sure the initial primary interface is set
|
dnl Make sure the initial primary member is set
|
||||||
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | grep 'active-backup primary: p1'`"])
|
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | grep 'active-backup primary: p1'`"])
|
||||||
|
|
||||||
dnl Down the primary interface and verify that we switched. Then
|
dnl Down the primary member and verify that we switched. Then
|
||||||
dnl bring the primary back and verify that we switched back to the
|
dnl bring the primary back and verify that we switched back to the
|
||||||
dnl primary.
|
dnl primary.
|
||||||
ovs-appctl netdev-dummy/set-admin-state p1 down
|
ovs-appctl netdev-dummy/set-admin-state p1 down
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | fgrep 'slave p1: disabled'`"])
|
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | fgrep 'member p1: disabled'`"])
|
||||||
ovs-appctl netdev-dummy/set-admin-state p1 up
|
ovs-appctl netdev-dummy/set-admin-state p1 up
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC], [0], [dnl
|
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
bond_mode: active-backup
|
bond_mode: active-backup
|
||||||
bond may use recirculation: no, <del>
|
bond may use recirculation: no, <del>
|
||||||
@ -139,39 +139,39 @@ downdelay: 0 ms
|
|||||||
lacp_status: off
|
lacp_status: off
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: p1
|
active-backup primary: p1
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Now delete the primary and verify that the output shows that the
|
dnl Now delete the primary and verify that the output shows that the
|
||||||
dnl primary is no longer enslaved
|
dnl primary is no longer an member
|
||||||
ovs-vsctl --id=@p1 get Interface p1 -- remove Port bond0 interfaces @p1
|
ovs-vsctl --id=@p1 get Interface p1 -- remove Port bond0 interfaces @p1
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | fgrep 'active-backup primary: p1 (no such slave)'`"])
|
OVS_WAIT_UNTIL([test -n "`ovs-appctl bond/show | fgrep 'active-backup primary: p1 (no such member)'`"])
|
||||||
|
|
||||||
dnl Now re-add the primary and verify that the output shows that the
|
dnl Now re-add the primary and verify that the output shows that the
|
||||||
dnl primary is available again.
|
dnl primary is available again.
|
||||||
dnl
|
dnl
|
||||||
dnl First, get the UUIDs of the interfaces that exist on bond0.
|
dnl First, get the UUIDs of the members that exist on bond0.
|
||||||
dnl Strip the trailing ] so that we can add a new UUID to the end.
|
dnl Strip the trailing ] so that we can add a new UUID to the end.
|
||||||
uuids=`ovs-vsctl get Port bond0 interfaces | sed -e 's/]//'`
|
uuids=`ovs-vsctl get Port bond0 interfaces | sed -e 's/]//'`
|
||||||
dnl Create a new port "p1" and add its UUID to the set of interfaces
|
dnl Create a new port "p1" and add its UUID to the set of members
|
||||||
dnl on bond0.
|
dnl on bond0.
|
||||||
ovs-vsctl \
|
ovs-vsctl \
|
||||||
--id=@p1 create Interface name=p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
|
--id=@p1 create Interface name=p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p1.sock ofport_request=1 -- \
|
||||||
set Port bond0 interfaces="$uuids, @p1]"
|
set Port bond0 interfaces="$uuids, @p1]"
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC], [0], [dnl
|
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
bond_mode: active-backup
|
bond_mode: active-backup
|
||||||
bond may use recirculation: no, <del>
|
bond may use recirculation: no, <del>
|
||||||
@ -181,16 +181,16 @@ downdelay: 0 ms
|
|||||||
lacp_status: off
|
lacp_status: off
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: p1
|
active-backup primary: p1
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -198,7 +198,7 @@ slave p3: enabled
|
|||||||
dnl Switch to another primary
|
dnl Switch to another primary
|
||||||
ovs-vsctl set port bond0 other_config:bond-primary=p2
|
ovs-vsctl set port bond0 other_config:bond-primary=p2
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC], [0], [dnl
|
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
bond_mode: active-backup
|
bond_mode: active-backup
|
||||||
bond may use recirculation: no, <del>
|
bond may use recirculation: no, <del>
|
||||||
@ -208,16 +208,16 @@ downdelay: 0 ms
|
|||||||
lacp_status: off
|
lacp_status: off
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: p2
|
active-backup primary: p2
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -225,7 +225,7 @@ slave p3: enabled
|
|||||||
dnl Remove the "bond-primary" config directive from the bond.
|
dnl Remove the "bond-primary" config directive from the bond.
|
||||||
AT_CHECK([ovs-vsctl remove Port bond0 other_config bond-primary])
|
AT_CHECK([ovs-vsctl remove Port bond0 other_config bond-primary])
|
||||||
ovs-appctl time/warp 100
|
ovs-appctl time/warp 100
|
||||||
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_SLAVE_MAC], [0], [dnl
|
OVS_WAIT_UNTIL([ovs-appctl bond/show | STRIP_RECIRC_ID | STRIP_ACTIVE_MEMBER_MAC], [0], [dnl
|
||||||
---- bond0 ----
|
---- bond0 ----
|
||||||
bond_mode: active-backup
|
bond_mode: active-backup
|
||||||
bond may use recirculation: no, <del>
|
bond may use recirculation: no, <del>
|
||||||
@ -235,16 +235,16 @@ downdelay: 0 ms
|
|||||||
lacp_status: off
|
lacp_status: off
|
||||||
lacp_fallback_ab: false
|
lacp_fallback_ab: false
|
||||||
active-backup primary: <none>
|
active-backup primary: <none>
|
||||||
<active slave mac del>
|
<active member mac del>
|
||||||
|
|
||||||
slave p1: enabled
|
member p1: enabled
|
||||||
active slave
|
active member
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p2: enabled
|
member p2: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
slave p3: enabled
|
member p3: enabled
|
||||||
may_enable: true
|
may_enable: true
|
||||||
|
|
||||||
])
|
])
|
||||||
@ -253,8 +253,8 @@ OVS_VSWITCHD_STOP
|
|||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([ofproto-dpif - active-backup bonding (without primary)])
|
AT_SETUP([ofproto-dpif - active-backup bonding (without primary)])
|
||||||
dnl Create br0 with interfaces p1, p2 and p7, creating bond0 with p1 and p2
|
dnl Create br0 with members p1, p2 and p7, creating bond0 with p1 and p2
|
||||||
dnl and br1 with interfaces p3, p4 and p8.
|
dnl and br1 with members p3, p4 and p8.
|
||||||
dnl toggle p1,p2 of bond0 up and down to test bonding in active-backup mode.
|
dnl toggle p1,p2 of bond0 up and down to test bonding in active-backup mode.
|
||||||
OVS_VSWITCHD_START(
|
OVS_VSWITCHD_START(
|
||||||
[add-bond br0 bond0 p1 p2 bond_mode=active-backup --\
|
[add-bond br0 bond0 p1 p2 bond_mode=active-backup --\
|
||||||
@ -300,8 +300,8 @@ OVS_VSWITCHD_STOP
|
|||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([ofproto-dpif - balance-slb bonding])
|
AT_SETUP([ofproto-dpif - balance-slb bonding])
|
||||||
# Create br0 with interfaces bond0(p1, p2, p3) and p7,
|
# Create br0 with members bond0(p1, p2, p3) and p7,
|
||||||
# and br1 with interfaces p4, p5, p6 and p8.
|
# and br1 with members p4, p5, p6 and p8.
|
||||||
# p1 <-> p4, p2 <-> p5, p3 <-> p6
|
# p1 <-> p4, p2 <-> p5, p3 <-> p6
|
||||||
# Send some traffic, make sure the traffic are spread based on source mac.
|
# Send some traffic, make sure the traffic are spread based on source mac.
|
||||||
OVS_VSWITCHD_START(
|
OVS_VSWITCHD_START(
|
||||||
@ -343,8 +343,8 @@ OVS_VSWITCHD_STOP
|
|||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([ofproto-dpif - balance-tcp bonding])
|
AT_SETUP([ofproto-dpif - balance-tcp bonding])
|
||||||
# Create br0 with interfaces bond0(p1, p2, p3) and p7,
|
# Create br0 with members bond0(p1, p2, p3) and p7,
|
||||||
# and br1 with interfaces bond1(p4, p5, p6) and p8.
|
# and br1 with members bond1(p4, p5, p6) and p8.
|
||||||
# bond0 <-> bond1
|
# bond0 <-> bond1
|
||||||
# Send some traffic, make sure the traffic are spread based on L4 headers.
|
# Send some traffic, make sure the traffic are spread based on L4 headers.
|
||||||
OVS_VSWITCHD_START(
|
OVS_VSWITCHD_START(
|
||||||
@ -2185,7 +2185,7 @@ cookie=0xd dl_src=60:66:66:66:00:02 actions=pop_mpls:0x0800,load:0xa000001->OXM_
|
|||||||
cookie=0xd dl_src=60:66:66:66:00:03 actions=pop_mpls:0x0800,move:OXM_OF_IPV4_DST[[]]->OXM_OF_IPV4_SRC[[]],controller
|
cookie=0xd dl_src=60:66:66:66:00:03 actions=pop_mpls:0x0800,move:OXM_OF_IPV4_DST[[]]->OXM_OF_IPV4_SRC[[]],controller
|
||||||
cookie=0xd dl_src=60:66:66:66:00:04 actions=pop_mpls:0x0800,push:OXM_OF_IPV4_DST[[]],pop:OXM_OF_IPV4_SRC[[]],controller
|
cookie=0xd dl_src=60:66:66:66:00:04 actions=pop_mpls:0x0800,push:OXM_OF_IPV4_DST[[]],pop:OXM_OF_IPV4_SRC[[]],controller
|
||||||
cookie=0xd dl_src=60:66:66:66:00:05 actions=pop_mpls:0x0800,multipath(eth_src,50,modulo_n,1,0,OXM_OF_IPV4_SRC[[0..7]]),controller
|
cookie=0xd dl_src=60:66:66:66:00:05 actions=pop_mpls:0x0800,multipath(eth_src,50,modulo_n,1,0,OXM_OF_IPV4_SRC[[0..7]]),controller
|
||||||
cookie=0xd dl_src=60:66:66:66:00:06 actions=pop_mpls:0x0800,bundle_load(eth_src,50,hrw,ofport,OXM_OF_IPV4_SRC[[0..15]],slaves:1,2),controller
|
cookie=0xd dl_src=60:66:66:66:00:06 actions=pop_mpls:0x0800,bundle_load(eth_src,50,hrw,ofport,OXM_OF_IPV4_SRC[[0..15]],members:1,2),controller
|
||||||
cookie=0xd dl_src=60:66:66:66:00:07 actions=pop_mpls:0x0800,learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,OXM_OF_IPV4_SRC[[]]=OXM_OF_IPV4_DST[[]]),controller
|
cookie=0xd dl_src=60:66:66:66:00:07 actions=pop_mpls:0x0800,learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,OXM_OF_IPV4_SRC[[]]=OXM_OF_IPV4_DST[[]]),controller
|
||||||
|
|
||||||
cookie=0xd dl_src=60:66:66:66:00:08 actions=pop_mpls:0x0806,resubmit(1,1)
|
cookie=0xd dl_src=60:66:66:66:00:08 actions=pop_mpls:0x0806,resubmit(1,1)
|
||||||
@ -3183,7 +3183,7 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
|
|||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:03 actions=pop_mpls:0x0800,move:NXM_OF_IP_DST[[]]->NXM_OF_IP_SRC[[]],CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:03 actions=pop_mpls:0x0800,move:NXM_OF_IP_DST[[]]->NXM_OF_IP_SRC[[]],CONTROLLER:65535
|
||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:04 actions=pop_mpls:0x0800,push:NXM_OF_IP_DST[[]],pop:NXM_OF_IP_SRC[[]],CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:04 actions=pop_mpls:0x0800,push:NXM_OF_IP_DST[[]],pop:NXM_OF_IP_SRC[[]],CONTROLLER:65535
|
||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:05 actions=pop_mpls:0x0800,multipath(eth_src,50,modulo_n,1,0,NXM_OF_IP_SRC[[0..7]]),CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:05 actions=pop_mpls:0x0800,multipath(eth_src,50,modulo_n,1,0,NXM_OF_IP_SRC[[0..7]]),CONTROLLER:65535
|
||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:06 actions=pop_mpls:0x0800,bundle_load(eth_src,50,hrw,ofport,NXM_OF_IP_SRC[[0..15]],slaves:1,2),CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:06 actions=pop_mpls:0x0800,bundle_load(eth_src,50,hrw,ofport,NXM_OF_IP_SRC[[0..15]],members:1,2),CONTROLLER:65535
|
||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:07 actions=pop_mpls:0x0800,learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,NXM_OF_IP_SRC[[]]=NXM_OF_IP_DST[[]]),CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:07 actions=pop_mpls:0x0800,learn(table=1,hard_timeout=60,eth_type=0x800,nw_proto=6,NXM_OF_IP_SRC[[]]=NXM_OF_IP_DST[[]]),CONTROLLER:65535
|
||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:09 actions=resubmit(,2),CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:09 actions=resubmit(,2),CONTROLLER:65535
|
||||||
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:0a actions=pop_mpls:0x0800,mod_nw_dst:10.0.0.1,CONTROLLER:65535
|
cookie=0xd, n_packets=3, n_bytes=186, dl_src=60:66:66:66:00:0a actions=pop_mpls:0x0800,mod_nw_dst:10.0.0.1,CONTROLLER:65535
|
||||||
@ -8634,8 +8634,8 @@ OVS_VSWITCHD_STOP
|
|||||||
AT_CLEANUP
|
AT_CLEANUP
|
||||||
|
|
||||||
AT_SETUP([ofproto-dpif megaflow - normal, balance-tcp bonding])
|
AT_SETUP([ofproto-dpif megaflow - normal, balance-tcp bonding])
|
||||||
# Create bond0 on br0 with interfaces p0 and p1
|
# Create bond0 on br0 with members p0 and p1
|
||||||
# and bond1 on br1 with interfaces p2 and p3
|
# and bond1 on br1 with members p2 and p3
|
||||||
# with p0 patched to p2 and p1 patched to p3.
|
# with p0 patched to p2 and p1 patched to p3.
|
||||||
OVS_VSWITCHD_START(
|
OVS_VSWITCHD_START(
|
||||||
[add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
[add-bond br0 bond0 p0 p1 bond_mode=balance-tcp lacp=active \
|
||||||
@ -9023,7 +9023,7 @@ AT_CHECK([ovs-appctl bfd/show | sed -n '/^.*Session State:.*/p'], [0], [dnl
|
|||||||
Local Session State: up
|
Local Session State: up
|
||||||
Remote Session State: up
|
Remote Session State: up
|
||||||
])
|
])
|
||||||
# bond/show should show 'may-enable: true' for all slaves.
|
# bond/show should show 'may-enable: true' for all members.
|
||||||
AT_CHECK([ovs-appctl bond/show | sed -n '/^.*may_enable:.*/p'], [0], [dnl
|
AT_CHECK([ovs-appctl bond/show | sed -n '/^.*may_enable:.*/p'], [0], [dnl
|
||||||
may_enable: true
|
may_enable: true
|
||||||
may_enable: true
|
may_enable: true
|
||||||
@ -11027,7 +11027,7 @@ AT_CHECK([ovs-vsctl add-port br0 p2 -- set int p2 type=dummy mtu_request=1600])
|
|||||||
AT_CHECK([ovs-vsctl wait-until Interface p2 mtu=1600])
|
AT_CHECK([ovs-vsctl wait-until Interface p2 mtu=1600])
|
||||||
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1600])
|
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1600])
|
||||||
|
|
||||||
# Explicitly set mtu_request on the internal interface. This should prevent
|
# Explicitly set mtu_request on the internal member. This should prevent
|
||||||
# the MTU from being overriden.
|
# the MTU from being overriden.
|
||||||
AT_CHECK([ovs-vsctl set int br0 mtu_request=1700])
|
AT_CHECK([ovs-vsctl set int br0 mtu_request=1700])
|
||||||
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1700])
|
AT_CHECK([ovs-vsctl wait-until Interface br0 mtu=1700])
|
||||||
|
@ -6322,12 +6322,12 @@ AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl
|
|||||||
OFPT_ERROR: OFPBAC_BAD_SET_LEN
|
OFPT_ERROR: OFPBAC_BAD_SET_LEN
|
||||||
])
|
])
|
||||||
|
|
||||||
AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=bundle_load(eth_src,50,hrw,ofport,tun_metadata1[[0..31]], slaves:4,8)"], [1], [], [stderr])
|
AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=bundle_load(eth_src,50,hrw,ofport,tun_metadata1[[0..31]], members:4,8)"], [1], [], [stderr])
|
||||||
AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl
|
AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl
|
||||||
OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD
|
OFPT_ERROR: NXFMFC_INVALID_TLV_FIELD
|
||||||
])
|
])
|
||||||
|
|
||||||
AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=bundle_load(eth_src,50,hrw,ofport,tun_metadata0[[32..63]], slaves:4,8)"], [1], [], [stderr])
|
AT_CHECK([ovs-ofctl add-flow br0 "in_port=2 actions=bundle_load(eth_src,50,hrw,ofport,tun_metadata0[[32..63]], members:4,8)"], [1], [], [stderr])
|
||||||
AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl
|
AT_CHECK([strip_xids < stderr | sed '/FLOW_MOD/,$d'], [0], [dnl
|
||||||
OFPT_ERROR: OFPBAC_BAD_SET_LEN
|
OFPT_ERROR: OFPBAC_BAD_SET_LEN
|
||||||
])
|
])
|
||||||
|
@ -413,20 +413,20 @@ actions=multipath(eth_src, 50, hrw, 12, 0, NXM_NX_REG0[0..3]),multipath(symmetri
|
|||||||
table=1,actions=drop
|
table=1,actions=drop
|
||||||
tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop
|
tun_id=0x1234000056780000/0xffff0000ffff0000,actions=drop
|
||||||
metadata=0x1234ffff5678ffff/0xffff0000ffff0000,actions=drop
|
metadata=0x1234ffff5678ffff/0xffff0000ffff0000,actions=drop
|
||||||
actions=bundle(eth_src,50,active_backup,ofport,slaves:1)
|
actions=bundle(eth_src,50,active_backup,ofport,members:1)
|
||||||
actions=bundle(symmetric_l4,60,hrw,ofport,slaves:2,3)
|
actions=bundle(symmetric_l4,60,hrw,ofport,members:2,3)
|
||||||
actions=bundle(symmetric_l4,60,hrw,ofport,slaves:)
|
actions=bundle(symmetric_l4,60,hrw,ofport,members:)
|
||||||
actions=bundle(symmetric_l3,60,hrw,ofport,slaves:2,3)
|
actions=bundle(symmetric_l3,60,hrw,ofport,members:2,3)
|
||||||
actions=bundle(symmetric_l3,60,hrw,ofport,slaves:)
|
actions=bundle(symmetric_l3,60,hrw,ofport,members:)
|
||||||
actions=output:1,bundle(eth_src,0,hrw,ofport,slaves:1),output:2
|
actions=output:1,bundle(eth_src,0,hrw,ofport,members:1),output:2
|
||||||
actions=bundle_load(eth_src,50,active_backup,ofport,reg0,slaves:1)
|
actions=bundle_load(eth_src,50,active_backup,ofport,reg0,members:1)
|
||||||
actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..15],slaves:2,3)
|
actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..15],members:2,3)
|
||||||
actions=bundle_load(symmetric_l4,60,hrw,ofport,reg0[0..15],slaves:[2,3])
|
actions=bundle_load(symmetric_l4,60,hrw,ofport,reg0[0..15],members:[2,3])
|
||||||
actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..30],slaves:)
|
actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..30],members:)
|
||||||
actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..15],slaves:2,3)
|
actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..15],members:2,3)
|
||||||
actions=bundle_load(symmetric_l3,60,hrw,ofport,reg0[0..15],slaves:[2,3])
|
actions=bundle_load(symmetric_l3,60,hrw,ofport,reg0[0..15],members:[2,3])
|
||||||
actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..30],slaves:)
|
actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..30],members:)
|
||||||
actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],slaves:1),output:2
|
actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],members:1),output:2
|
||||||
actions=resubmit:1,resubmit(2),resubmit(,3),resubmit(2,3)
|
actions=resubmit:1,resubmit(2),resubmit(,3),resubmit(2,3)
|
||||||
send_flow_rem,actions=output:1,output:NXM_NX_REG0,output:2,output:reg1[16..31],output:3
|
send_flow_rem,actions=output:1,output:NXM_NX_REG0,output:2,output:reg1[16..31],output:3
|
||||||
check_overlap,actions=output:1,exit,output:2
|
check_overlap,actions=output:1,exit,output:2
|
||||||
@ -469,20 +469,20 @@ NXT_FLOW_MOD: ADD table:255 actions=multipath(eth_src,50,hrw,12,0,NXM_NX_REG0[0.
|
|||||||
NXT_FLOW_MOD: ADD table:1 actions=drop
|
NXT_FLOW_MOD: ADD table:1 actions=drop
|
||||||
NXT_FLOW_MOD: ADD table:255 tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop
|
NXT_FLOW_MOD: ADD table:255 tun_id=0x1234000056780000/0xffff0000ffff0000 actions=drop
|
||||||
NXT_FLOW_MOD: ADD table:255 metadata=0x1234000056780000/0xffff0000ffff0000 actions=drop
|
NXT_FLOW_MOD: ADD table:255 metadata=0x1234000056780000/0xffff0000ffff0000 actions=drop
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle(eth_src,50,active_backup,ofport,slaves:1)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle(eth_src,50,active_backup,ofport,members:1)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l4,60,hrw,ofport,slaves:2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l4,60,hrw,ofport,members:2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l4,60,hrw,ofport,slaves:)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l4,60,hrw,ofport,members:)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l3,60,hrw,ofport,slaves:2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l3,60,hrw,ofport,members:2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l3,60,hrw,ofport,slaves:)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle(symmetric_l3,60,hrw,ofport,members:)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=output:1,bundle(eth_src,0,hrw,ofport,slaves:1),output:2
|
NXT_FLOW_MOD: ADD table:255 actions=output:1,bundle(eth_src,0,hrw,ofport,members:1),output:2
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(eth_src,50,active_backup,ofport,NXM_NX_REG0[],slaves:1)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(eth_src,50,active_backup,ofport,NXM_NX_REG0[],members:1)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..15],slaves:2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..15],members:2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..15],slaves:2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..15],members:2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..30],slaves:)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..30],members:)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..15],slaves:2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..15],members:2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..15],slaves:2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..15],members:2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..30],slaves:)
|
NXT_FLOW_MOD: ADD table:255 actions=bundle_load(symmetric_l3,60,hrw,ofport,NXM_NX_REG0[0..30],members:)
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],slaves:1),output:2
|
NXT_FLOW_MOD: ADD table:255 actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],members:1),output:2
|
||||||
NXT_FLOW_MOD: ADD table:255 actions=resubmit:1,resubmit:2,resubmit(,3),resubmit(2,3)
|
NXT_FLOW_MOD: ADD table:255 actions=resubmit:1,resubmit:2,resubmit(,3),resubmit(2,3)
|
||||||
NXT_FLOW_MOD: ADD table:255 send_flow_rem actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
|
NXT_FLOW_MOD: ADD table:255 send_flow_rem actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
|
||||||
NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
|
NXT_FLOW_MOD: ADD table:255 check_overlap actions=output:1,exit,output:2
|
||||||
|
@ -25,28 +25,28 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define N_FLOWS 50000
|
#define N_FLOWS 50000
|
||||||
#define MAX_SLAVES 8 /* Maximum supported by this test framework. */
|
#define MAX_MEMBERS 8 /* Maximum supported by this test framework. */
|
||||||
|
|
||||||
struct slave {
|
struct member {
|
||||||
ofp_port_t slave_id;
|
ofp_port_t member_id;
|
||||||
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
size_t flow_count;
|
size_t flow_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct slave_group {
|
struct member_group {
|
||||||
size_t n_slaves;
|
size_t n_members;
|
||||||
struct slave slaves[MAX_SLAVES];
|
struct member members[MAX_MEMBERS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct slave *
|
static struct member *
|
||||||
slave_lookup(struct slave_group *sg, ofp_port_t slave_id)
|
member_lookup(struct member_group *sg, ofp_port_t member_id)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < sg->n_slaves; i++) {
|
for (i = 0; i < sg->n_members; i++) {
|
||||||
if (sg->slaves[i].slave_id == slave_id) {
|
if (sg->members[i].member_id == member_id) {
|
||||||
return &sg->slaves[i];
|
return &sg->members[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,12 +54,12 @@ slave_lookup(struct slave_group *sg, ofp_port_t slave_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
slave_enabled_cb(ofp_port_t slave_id, void *aux)
|
member_enabled_cb(ofp_port_t member_id, void *aux)
|
||||||
{
|
{
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
|
|
||||||
slave = slave_lookup(aux, slave_id);
|
member = member_lookup(aux, member_id);
|
||||||
return slave ? slave->enabled : false;
|
return member ? member->enabled : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ofpact_bundle *
|
static struct ofpact_bundle *
|
||||||
@ -80,8 +80,8 @@ parse_bundle_actions(char *actions)
|
|||||||
bundle = ofpact_get_BUNDLE(xmemdup(action, action->len));
|
bundle = ofpact_get_BUNDLE(xmemdup(action, action->len));
|
||||||
ofpbuf_uninit(&ofpacts);
|
ofpbuf_uninit(&ofpacts);
|
||||||
|
|
||||||
if (bundle->n_slaves > MAX_SLAVES) {
|
if (bundle->n_members > MAX_MEMBERS) {
|
||||||
ovs_fatal(0, "At most %u slaves are supported", MAX_SLAVES);
|
ovs_fatal(0, "At most %u members are supported", MAX_MEMBERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bundle;
|
return bundle;
|
||||||
@ -109,7 +109,7 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
struct ofpact_bundle *bundle;
|
struct ofpact_bundle *bundle;
|
||||||
struct flow *flows;
|
struct flow *flows;
|
||||||
size_t i, n_permute, old_n_enabled;
|
size_t i, n_permute, old_n_enabled;
|
||||||
struct slave_group sg;
|
struct member_group sg;
|
||||||
int old_active;
|
int old_active;
|
||||||
|
|
||||||
set_program_name(argv[0]);
|
set_program_name(argv[0]);
|
||||||
@ -120,17 +120,17 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
|
|
||||||
bundle = parse_bundle_actions(argv[1]);
|
bundle = parse_bundle_actions(argv[1]);
|
||||||
|
|
||||||
/* Generate 'slaves' array. */
|
/* Generate 'members' array. */
|
||||||
sg.n_slaves = 0;
|
sg.n_members = 0;
|
||||||
for (i = 0; i < bundle->n_slaves; i++) {
|
for (i = 0; i < bundle->n_members; i++) {
|
||||||
ofp_port_t slave_id = bundle->slaves[i];
|
ofp_port_t member_id = bundle->members[i];
|
||||||
|
|
||||||
if (slave_lookup(&sg, slave_id)) {
|
if (member_lookup(&sg, member_id)) {
|
||||||
ovs_fatal(0, "Redundant slaves are not supported. ");
|
ovs_fatal(0, "Redundant members are not supported. ");
|
||||||
}
|
}
|
||||||
|
|
||||||
sg.slaves[sg.n_slaves].slave_id = slave_id;
|
sg.members[sg.n_members].member_id = member_id;
|
||||||
sg.n_slaves++;
|
sg.n_members++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate flows. */
|
/* Generate flows. */
|
||||||
@ -141,14 +141,14 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Cycles through each possible liveness permutation for the given
|
/* Cycles through each possible liveness permutation for the given
|
||||||
* n_slaves. The initial state is equivalent to all slaves down, so we
|
* n_members. The initial state is equivalent to all members down, so we
|
||||||
* skip it by starting at i = 1. We do one extra iteration to cover
|
* skip it by starting at i = 1. We do one extra iteration to cover
|
||||||
* transitioning from the final state back to the initial state. */
|
* transitioning from the final state back to the initial state. */
|
||||||
old_n_enabled = 0;
|
old_n_enabled = 0;
|
||||||
old_active = -1;
|
old_active = -1;
|
||||||
n_permute = 1 << sg.n_slaves;
|
n_permute = 1 << sg.n_members;
|
||||||
for (i = 1; i <= n_permute + 1; i++) {
|
for (i = 1; i <= n_permute + 1; i++) {
|
||||||
struct slave *slave;
|
struct member *member;
|
||||||
size_t j, n_enabled, changed;
|
size_t j, n_enabled, changed;
|
||||||
double disruption, perfect;
|
double disruption, perfect;
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
@ -156,27 +156,27 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
|
|
||||||
mask = i % n_permute;
|
mask = i % n_permute;
|
||||||
|
|
||||||
/* Gray coding ensures that in each iteration exactly one slave
|
/* Gray coding ensures that in each iteration exactly one member
|
||||||
* changes its liveness. This makes the expected disruption a bit
|
* changes its liveness. This makes the expected disruption a bit
|
||||||
* easier to calculate, and is likely similar to how failures will be
|
* easier to calculate, and is likely similar to how failures will be
|
||||||
* experienced in the wild. */
|
* experienced in the wild. */
|
||||||
mask = mask ^ (mask >> 1);
|
mask = mask ^ (mask >> 1);
|
||||||
|
|
||||||
/* Initialize slaves. */
|
/* Initialize members. */
|
||||||
n_enabled = 0;
|
n_enabled = 0;
|
||||||
for (j = 0; j < sg.n_slaves; j++) {
|
for (j = 0; j < sg.n_members; j++) {
|
||||||
slave = &sg.slaves[j];
|
member = &sg.members[j];
|
||||||
slave->flow_count = 0;
|
member->flow_count = 0;
|
||||||
slave->enabled = ((1 << j) & mask) != 0;
|
member->enabled = ((1 << j) & mask) != 0;
|
||||||
|
|
||||||
if (slave->enabled) {
|
if (member->enabled) {
|
||||||
n_enabled++;
|
n_enabled++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
active = -1;
|
active = -1;
|
||||||
for (j = 0; j < sg.n_slaves; j++) {
|
for (j = 0; j < sg.n_members; j++) {
|
||||||
if (sg.slaves[j].enabled) {
|
if (sg.members[j].enabled) {
|
||||||
active = j;
|
active = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -185,19 +185,19 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
changed = 0;
|
changed = 0;
|
||||||
for (j = 0; j < N_FLOWS; j++) {
|
for (j = 0; j < N_FLOWS; j++) {
|
||||||
struct flow *flow = &flows[j];
|
struct flow *flow = &flows[j];
|
||||||
ofp_port_t old_slave_id, ofp_port;
|
ofp_port_t old_member_id, ofp_port;
|
||||||
struct flow_wildcards wc;
|
struct flow_wildcards wc;
|
||||||
|
|
||||||
old_slave_id = u16_to_ofp(flow->regs[0]);
|
old_member_id = u16_to_ofp(flow->regs[0]);
|
||||||
ofp_port = bundle_execute(bundle, flow, &wc, slave_enabled_cb,
|
ofp_port = bundle_execute(bundle, flow, &wc, member_enabled_cb,
|
||||||
&sg);
|
&sg);
|
||||||
flow->regs[0] = ofp_to_u16(ofp_port);
|
flow->regs[0] = ofp_to_u16(ofp_port);
|
||||||
|
|
||||||
if (ofp_port != OFPP_NONE) {
|
if (ofp_port != OFPP_NONE) {
|
||||||
slave_lookup(&sg, ofp_port)->flow_count++;
|
member_lookup(&sg, ofp_port)->flow_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_slave_id != ofp_port) {
|
if (old_member_id != ofp_port) {
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,23 +208,23 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
if (old_n_enabled || n_enabled) {
|
if (old_n_enabled || n_enabled) {
|
||||||
perfect = 1.0 / MAX(old_n_enabled, n_enabled);
|
perfect = 1.0 / MAX(old_n_enabled, n_enabled);
|
||||||
} else {
|
} else {
|
||||||
/* This will happen when 'sg.n_slaves' is 0. */
|
/* This will happen when 'sg.n_members' is 0. */
|
||||||
perfect = 0;
|
perfect = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
disruption = changed / (double)N_FLOWS;
|
disruption = changed / (double)N_FLOWS;
|
||||||
printf("%s: disruption=%.2f (perfect=%.2f)",
|
printf("%s: disruption=%.2f (perfect=%.2f)",
|
||||||
mask_str(mask, sg.n_slaves), disruption, perfect);
|
mask_str(mask, sg.n_members), disruption, perfect);
|
||||||
|
|
||||||
for (j = 0 ; j < sg.n_slaves; j++) {
|
for (j = 0 ; j < sg.n_members; j++) {
|
||||||
slave = &sg.slaves[j];
|
member = &sg.members[j];
|
||||||
double flow_percent;
|
double flow_percent;
|
||||||
|
|
||||||
flow_percent = slave->flow_count / (double)N_FLOWS;
|
flow_percent = member->flow_count / (double)N_FLOWS;
|
||||||
printf( " %.2f", flow_percent);
|
printf( " %.2f", flow_percent);
|
||||||
|
|
||||||
if (slave->enabled) {
|
if (member->enabled) {
|
||||||
double perfect_fp;
|
double perfect_fp;
|
||||||
|
|
||||||
if (bundle->algorithm == NX_BD_ALG_ACTIVE_BACKUP) {
|
if (bundle->algorithm == NX_BD_ALG_ACTIVE_BACKUP) {
|
||||||
@ -234,16 +234,16 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fabs(flow_percent - perfect_fp) >= .01) {
|
if (fabs(flow_percent - perfect_fp) >= .01) {
|
||||||
fprintf(stderr, "%s: slave %d: flow_percentage=%.5f for"
|
fprintf(stderr, "%s: member %d: flow_percentage=%.5f for"
|
||||||
" differs from perfect=%.5f by more than .01\n",
|
" differs from perfect=%.5f by more than .01\n",
|
||||||
mask_str(mask, sg.n_slaves), slave->slave_id,
|
mask_str(mask, sg.n_members), member->member_id,
|
||||||
flow_percent, perfect_fp);
|
flow_percent, perfect_fp);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
} else if (slave->flow_count) {
|
} else if (member->flow_count) {
|
||||||
fprintf(stderr, "%s: slave %d: disabled slave received"
|
fprintf(stderr, "%s: member %d: disabled member received"
|
||||||
" flows.\n", mask_str(mask, sg.n_slaves),
|
" flows.\n", mask_str(mask, sg.n_members),
|
||||||
slave->slave_id);
|
member->member_id);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ test_bundle_main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (fabs(disruption - perfect) >= .01) {
|
if (fabs(disruption - perfect) >= .01) {
|
||||||
fprintf(stderr, "%s: disruption=%.5f differs from perfect=%.5f by"
|
fprintf(stderr, "%s: disruption=%.5f differs from perfect=%.5f by"
|
||||||
" more than .01\n", mask_str(mask, sg.n_slaves),
|
" more than .01\n", mask_str(mask, sg.n_members),
|
||||||
disruption, perfect);
|
disruption, perfect);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
|
@ -330,7 +330,8 @@ static void mirror_destroy(struct mirror *);
|
|||||||
static bool mirror_configure(struct mirror *);
|
static bool mirror_configure(struct mirror *);
|
||||||
static void mirror_refresh_stats(struct mirror *);
|
static void mirror_refresh_stats(struct mirror *);
|
||||||
|
|
||||||
static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *);
|
static void iface_configure_lacp(struct iface *,
|
||||||
|
struct lacp_member_settings *);
|
||||||
static bool iface_create(struct bridge *, const struct ovsrec_interface *,
|
static bool iface_create(struct bridge *, const struct ovsrec_interface *,
|
||||||
const struct ovsrec_port *);
|
const struct ovsrec_port *);
|
||||||
static bool iface_is_internal(const struct ovsrec_interface *iface,
|
static bool iface_is_internal(const struct ovsrec_interface *iface,
|
||||||
@ -1197,11 +1198,11 @@ port_configure(struct port *port)
|
|||||||
/* Get name. */
|
/* Get name. */
|
||||||
s.name = port->name;
|
s.name = port->name;
|
||||||
|
|
||||||
/* Get slaves. */
|
/* Get members. */
|
||||||
s.n_slaves = 0;
|
s.n_members = 0;
|
||||||
s.slaves = xmalloc(ovs_list_size(&port->ifaces) * sizeof *s.slaves);
|
s.members = xmalloc(ovs_list_size(&port->ifaces) * sizeof *s.members);
|
||||||
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
|
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
|
||||||
s.slaves[s.n_slaves++] = iface->ofp_port;
|
s.members[s.n_members++] = iface->ofp_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get VLAN tag. */
|
/* Get VLAN tag. */
|
||||||
@ -1270,16 +1271,16 @@ port_configure(struct port *port)
|
|||||||
if (s.lacp) {
|
if (s.lacp) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
s.lacp_slaves = xmalloc(s.n_slaves * sizeof *s.lacp_slaves);
|
s.lacp_members = xmalloc(s.n_members * sizeof *s.lacp_members);
|
||||||
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
|
LIST_FOR_EACH (iface, port_elem, &port->ifaces) {
|
||||||
iface_configure_lacp(iface, &s.lacp_slaves[i++]);
|
iface_configure_lacp(iface, &s.lacp_members[i++]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s.lacp_slaves = NULL;
|
s.lacp_members = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get bond settings. */
|
/* Get bond settings. */
|
||||||
if (s.n_slaves > 1) {
|
if (s.n_members > 1) {
|
||||||
s.bond = &bond_settings;
|
s.bond = &bond_settings;
|
||||||
port_configure_bond(port, &bond_settings);
|
port_configure_bond(port, &bond_settings);
|
||||||
} else {
|
} else {
|
||||||
@ -1297,9 +1298,9 @@ port_configure(struct port *port)
|
|||||||
|
|
||||||
/* Clean up. */
|
/* Clean up. */
|
||||||
free(s.cvlans);
|
free(s.cvlans);
|
||||||
free(s.slaves);
|
free(s.members);
|
||||||
free(s.trunks);
|
free(s.trunks);
|
||||||
free(s.lacp_slaves);
|
free(s.lacp_members);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pick local port hardware address and datapath ID for 'br'. */
|
/* Pick local port hardware address and datapath ID for 'br'. */
|
||||||
@ -2277,8 +2278,8 @@ find_local_hw_addr(const struct bridge *br, struct eth_addr *ea,
|
|||||||
} else {
|
} else {
|
||||||
/* Choose the interface whose MAC address will represent the port.
|
/* Choose the interface whose MAC address will represent the port.
|
||||||
* The Linux kernel bonding code always chooses the MAC address of
|
* The Linux kernel bonding code always chooses the MAC address of
|
||||||
* the first slave added to a bond, and the Fedora networking
|
* the first member added to a bond, and the Fedora networking
|
||||||
* scripts always add slaves to a bond in alphabetical order, so
|
* scripts always add members to a bond in alphabetical order, so
|
||||||
* for compatibility we choose the interface with the name that is
|
* for compatibility we choose the interface with the name that is
|
||||||
* first in alphabetical order. */
|
* first in alphabetical order. */
|
||||||
LIST_FOR_EACH (candidate, port_elem, &port->ifaces) {
|
LIST_FOR_EACH (candidate, port_elem, &port->ifaces) {
|
||||||
@ -2961,7 +2962,7 @@ port_refresh_bond_status(struct port *port, bool force_update)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bond_get_changed_active_slave(port->name, &mac, force_update)) {
|
if (bond_get_changed_active_member(port->name, &mac, force_update)) {
|
||||||
struct ds mac_s;
|
struct ds mac_s;
|
||||||
|
|
||||||
ds_init(&mac_s);
|
ds_init(&mac_s);
|
||||||
@ -4505,7 +4506,7 @@ port_configure_lacp(struct port *port, struct lacp_settings *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s)
|
iface_configure_lacp(struct iface *iface, struct lacp_member_settings *s)
|
||||||
{
|
{
|
||||||
int priority, portid, key;
|
int priority, portid, key;
|
||||||
|
|
||||||
@ -4601,9 +4602,9 @@ port_configure_bond(struct port *port, struct bond_settings *s)
|
|||||||
|
|
||||||
mac_s = port->cfg->bond_active_slave;
|
mac_s = port->cfg->bond_active_slave;
|
||||||
if (!mac_s || !ovs_scan(mac_s, ETH_ADDR_SCAN_FMT,
|
if (!mac_s || !ovs_scan(mac_s, ETH_ADDR_SCAN_FMT,
|
||||||
ETH_ADDR_SCAN_ARGS(s->active_slave_mac))) {
|
ETH_ADDR_SCAN_ARGS(s->active_member_mac))) {
|
||||||
/* OVSDB did not store the last active interface */
|
/* OVSDB did not store the last active interface */
|
||||||
s->active_slave_mac = eth_addr_zero;
|
s->active_member_mac = eth_addr_zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lb_output action is disabled by default. */
|
/* lb_output action is disabled by default. */
|
||||||
|
@ -198,46 +198,46 @@ These commands manage bonded ports on an Open vSwitch's bridges. To
|
|||||||
understand some of these commands, it is important to understand a
|
understand some of these commands, it is important to understand a
|
||||||
detail of the bonding implementation called ``source load balancing''
|
detail of the bonding implementation called ``source load balancing''
|
||||||
(SLB). Instead of directly assigning Ethernet source addresses to
|
(SLB). Instead of directly assigning Ethernet source addresses to
|
||||||
slaves, the bonding implementation computes a function that maps an
|
members, the bonding implementation computes a function that maps an
|
||||||
48-bit Ethernet source addresses into an 8-bit value (a ``MAC hash''
|
48-bit Ethernet source addresses into an 8-bit value (a ``MAC hash''
|
||||||
value). All of the Ethernet addresses that map to a single 8-bit
|
value). All of the Ethernet addresses that map to a single 8-bit
|
||||||
value are then assigned to a single slave.
|
value are then assigned to a single member.
|
||||||
.IP "\fBbond/list\fR"
|
.IP "\fBbond/list\fR"
|
||||||
Lists all of the bonds, and their slaves, on each bridge.
|
Lists all of the bonds, and their members, on each bridge.
|
||||||
.
|
.
|
||||||
.IP "\fBbond/show\fR [\fIport\fR]"
|
.IP "\fBbond/show\fR [\fIport\fR]"
|
||||||
Lists all of the bond-specific information (updelay, downdelay, time
|
Lists all of the bond-specific information (updelay, downdelay, time
|
||||||
until the next rebalance) about the given bonded \fIport\fR, or all
|
until the next rebalance) about the given bonded \fIport\fR, or all
|
||||||
bonded ports if no \fIport\fR is given. Also lists information about
|
bonded ports if no \fIport\fR is given. Also lists information about
|
||||||
each slave: whether it is enabled or disabled, the time to completion
|
each members: whether it is enabled or disabled, the time to completion
|
||||||
of an updelay or downdelay if one is in progress, whether it is the
|
of an updelay or downdelay if one is in progress, whether it is the
|
||||||
active slave, the hashes assigned to the slave. Any LACP information
|
active member, the hashes assigned to the member. Any LACP information
|
||||||
related to this bond may be found using the \fBlacp/show\fR command.
|
related to this bond may be found using the \fBlacp/show\fR command.
|
||||||
.
|
.
|
||||||
.IP "\fBbond/migrate\fR \fIport\fR \fIhash\fR \fIslave\fR"
|
.IP "\fBbond/migrate\fR \fIport\fR \fIhash\fR \fImember\fR"
|
||||||
Only valid for SLB bonds. Assigns a given MAC hash to a new slave.
|
Only valid for SLB bonds. Assigns a given MAC hash to a new member.
|
||||||
\fIport\fR specifies the bond port, \fIhash\fR the MAC hash to be
|
\fIport\fR specifies the bond port, \fIhash\fR the MAC hash to be
|
||||||
migrated (as a decimal number between 0 and 255), and \fIslave\fR the
|
migrated (as a decimal number between 0 and 255), and \fImember\fR the
|
||||||
new slave to be assigned.
|
new member to be assigned.
|
||||||
.IP
|
.IP
|
||||||
The reassignment is not permanent: rebalancing or fail-over will
|
The reassignment is not permanent: rebalancing or fail-over will
|
||||||
cause the MAC hash to be shifted to a new slave in the usual
|
cause the MAC hash to be shifted to a new member in the usual
|
||||||
manner.
|
manner.
|
||||||
.IP
|
.IP
|
||||||
A MAC hash cannot be migrated to a disabled slave.
|
A MAC hash cannot be migrated to a disabled member.
|
||||||
.IP "\fBbond/set\-active\-slave\fR \fIport\fR \fIslave\fR"
|
.IP "\fBbond/set\-active\-member\fR \fIport\fR \fImember\fR"
|
||||||
Sets \fIslave\fR as the active slave on \fIport\fR. \fIslave\fR must
|
Sets \fImember\fR as the active member on \fIport\fR. \fImember\fR must
|
||||||
currently be enabled.
|
currently be enabled.
|
||||||
.IP
|
.IP
|
||||||
The setting is not permanent: a new active slave will be selected
|
The setting is not permanent: a new active member will be selected
|
||||||
if \fIslave\fR becomes disabled.
|
if \fImember\fR becomes disabled.
|
||||||
.IP "\fBbond/enable\-slave\fR \fIport\fR \fIslave\fR"
|
.IP "\fBbond/enable\-member\fR \fIport\fR \fImember\fR"
|
||||||
.IQ "\fBbond/disable\-slave\fR \fIport\fR \fIslave\fR"
|
.IQ "\fBbond/disable\-member\fR \fIport\fR \fImember\fR"
|
||||||
Enables (or disables) \fIslave\fR on the given bond \fIport\fR, skipping any
|
Enables (or disables) \fImember\fR on the given bond \fIport\fR, skipping any
|
||||||
updelay (or downdelay).
|
updelay (or downdelay).
|
||||||
.IP
|
.IP
|
||||||
This setting is not permanent: it persists only until the carrier
|
This setting is not permanent: it persists only until the carrier
|
||||||
status of \fIslave\fR changes.
|
status of \fImember\fR changes.
|
||||||
.IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR] [\fIbasis\fR]"
|
.IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR] [\fIbasis\fR]"
|
||||||
Returns the hash value which would be used for \fImac\fR with \fIvlan\fR
|
Returns the hash value which would be used for \fImac\fR with \fIvlan\fR
|
||||||
and \fIbasis\fR if specified.
|
and \fIbasis\fR if specified.
|
||||||
@ -245,7 +245,7 @@ and \fIbasis\fR if specified.
|
|||||||
.IP "\fBlacp/show\fR [\fIport\fR]"
|
.IP "\fBlacp/show\fR [\fIport\fR]"
|
||||||
Lists all of the LACP related information about the given \fIport\fR:
|
Lists all of the LACP related information about the given \fIport\fR:
|
||||||
active or passive, aggregation key, system id, and system priority. Also
|
active or passive, aggregation key, system id, and system priority. Also
|
||||||
lists information about each slave: whether it is enabled or disabled,
|
lists information about each member: whether it is enabled or disabled,
|
||||||
whether it is attached or detached, port id and priority, actor
|
whether it is attached or detached, port id and priority, actor
|
||||||
information, and partner information. If \fIport\fR is not specified,
|
information, and partner information. If \fIport\fR is not specified,
|
||||||
then displays detailed information about all interfaces with CFM
|
then displays detailed information about all interfaces with CFM
|
||||||
@ -253,7 +253,7 @@ enabled.
|
|||||||
.
|
.
|
||||||
.IP "\fBlacp/stats-show\fR [\fIport\fR]"
|
.IP "\fBlacp/stats-show\fR [\fIport\fR]"
|
||||||
Lists various stats about LACP PDUs (number of RX/TX PDUs, bad PDUs received)
|
Lists various stats about LACP PDUs (number of RX/TX PDUs, bad PDUs received)
|
||||||
and slave state (number of time slave's state expired/defaulted and carrier
|
and member state (number of times its state expired/defaulted and carrier
|
||||||
status changed) for the given \fIport\fR. If \fIport\fR is not specified,
|
status changed) for the given \fIport\fR. If \fIport\fR is not specified,
|
||||||
then displays stats of all interfaces with LACP enabled.
|
then displays stats of all interfaces with LACP enabled.
|
||||||
.SS "DPCTL DATAPATH DEBUGGING COMMANDS"
|
.SS "DPCTL DATAPATH DEBUGGING COMMANDS"
|
||||||
|
@ -1949,15 +1949,16 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><code>balance-slb</code></dt>
|
<dt><code>balance-slb</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Balances flows among slaves based on source MAC address and output
|
Balances flows among members based on source MAC address and
|
||||||
VLAN, with periodic rebalancing as traffic patterns change.
|
output VLAN, with periodic rebalancing as traffic patterns change.
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt><code>active-backup</code></dt>
|
<dt><code>active-backup</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Assigns all flows to one slave, failing over to a backup slave when
|
Assigns all flows to one member, failing over to a backup
|
||||||
the active slave is disabled. This is the only bonding mode in which
|
member when the active member is disabled. This is the
|
||||||
interfaces may be plugged into different upstream switches.
|
only bonding mode in which interfaces may be plugged into different
|
||||||
|
upstream switches.
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
@ -1971,8 +1972,8 @@
|
|||||||
<dl>
|
<dl>
|
||||||
<dt><code>balance-tcp</code></dt>
|
<dt><code>balance-tcp</code></dt>
|
||||||
<dd>
|
<dd>
|
||||||
Balances flows among slaves based on L3 and L4 protocol information
|
Balances flows among members based on L3 and L4 protocol
|
||||||
such as IP addresses and TCP/UDP ports.
|
information such as IP addresses and TCP/UDP ports.
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
@ -1987,20 +1988,20 @@
|
|||||||
|
|
||||||
<column name="other_config" key="bond-hash-basis"
|
<column name="other_config" key="bond-hash-basis"
|
||||||
type='{"type": "integer"}'>
|
type='{"type": "integer"}'>
|
||||||
An integer hashed along with flows when choosing output slaves in load
|
An integer hashed along with flows when choosing output members
|
||||||
balanced bonds. When changed, all flows will be assigned different
|
in load balanced bonds. When changed, all flows will be assigned
|
||||||
hash values possibly causing slave selection decisions to change. Does
|
different hash values possibly causing member selection
|
||||||
not affect bonding modes which do not employ load balancing such as
|
decisions to change. Does not affect bonding modes which do not employ
|
||||||
<code>active-backup</code>.
|
load balancing such as <code>active-backup</code>.
|
||||||
</column>
|
</column>
|
||||||
|
|
||||||
<column name="other_config" key="lb-output-action"
|
<column name="other_config" key="lb-output-action"
|
||||||
type='{"type": "boolean"}'>
|
type='{"type": "boolean"}'>
|
||||||
Enable/disable usage of optimized <code>lb_output</code> action for
|
Enable/disable usage of optimized <code>lb_output</code> action for
|
||||||
balancing flows among output slaves in load balanced bonds in
|
balancing flows among output members in load balanced bonds in
|
||||||
<code>balance-tcp</code>. When enabled, it uses optimized path for
|
<code>balance-tcp</code>. When enabled, it uses optimized path for
|
||||||
balance-tcp mode by using rss hash and avoids recirculation.
|
balance-tcp mode by using rss hash and avoids recirculation. This knob
|
||||||
This knob does not affect other balancing modes.
|
does not affect other balancing modes.
|
||||||
</column>
|
</column>
|
||||||
|
|
||||||
<column name="other_config" key="bond-primary"
|
<column name="other_config" key="bond-primary"
|
||||||
@ -2390,7 +2391,8 @@
|
|||||||
</group>
|
</group>
|
||||||
|
|
||||||
<column name="bond_active_slave">
|
<column name="bond_active_slave">
|
||||||
For a bonded port, record the mac address of the current active slave.
|
For a bonded port, record the MAC address of the current active
|
||||||
|
member.
|
||||||
</column>
|
</column>
|
||||||
|
|
||||||
<group title="Port Statistics">
|
<group title="Port Statistics">
|
||||||
@ -2480,7 +2482,8 @@
|
|||||||
<li>For the local interface, the default is the lowest-numbered MAC
|
<li>For the local interface, the default is the lowest-numbered MAC
|
||||||
address among the other bridge ports, either the value of the
|
address among the other bridge ports, either the value of the
|
||||||
<ref table="Port" column="mac"/> in its <ref table="Port"/> record,
|
<ref table="Port" column="mac"/> in its <ref table="Port"/> record,
|
||||||
if set, or its actual MAC (for bonded ports, the MAC of its slave
|
if set, or its actual MAC (for bonded ports, the MAC of its
|
||||||
|
member
|
||||||
whose name is first in alphabetical order). Internal ports and
|
whose name is first in alphabetical order). Internal ports and
|
||||||
bridge ports that are used as port mirroring destinations (see the
|
bridge ports that are used as port mirroring destinations (see the
|
||||||
<ref table="Mirror"/> table) are ignored.</li>
|
<ref table="Mirror"/> table) are ignored.</li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user