lib/packet: add Link Aggregation Control Protocol

Signed-off-by: Yuichi Ito <ito.yuichi0@gmal.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Yuichi Ito 2013-07-24 02:58:36 +09:00 committed by FUJITA Tomonori
parent d0cd6e1533
commit a1b6d39f9d
4 changed files with 1680 additions and 0 deletions

View File

@ -57,3 +57,8 @@ Protocol Header classes
:members: :members:
.. autoclass:: ryu.lib.packet.vrrp.vrrpv3 .. autoclass:: ryu.lib.packet.vrrp.vrrpv3
:members: :members:
.. autoclass:: ryu.lib.packet.slow.slow
:members:
.. autoclass:: ryu.lib.packet.slow.lacp
:members:

577
ryu/lib/packet/slow.py Executable file
View File

@ -0,0 +1,577 @@
# Copyright (C) 2013 Nippon Telegraph and Telephone Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import struct
from . import packet_base
from ryu.lib import mac
# Slow Protocol Multicast destination
SLOW_PROTOCOL_MULTICAST = '\x01\x80\xc2\x00\x00\x02'
# Slow Protocol SubType
SLOW_SUBTYPE_LACP = 0x01
SLOW_SUBTYPE_MARKER = 0x02
SLOW_SUBTYPE_OAM = 0x03
SLOW_SUBTYPE_OSSP = 0x0a
class slow(packet_base.PacketBase):
"""Slow Protocol header decoder class.
This class has only the parser method.
http://standards.ieee.org/getieee802/download/802.3-2012_section5.pdf
Slow Protocols Subtypes
+---------------+--------------------------------------------------+
| Subtype Value | Protocol Name |
+===============+==================================================+
| 0 | Unused - Illegal Value |
+---------------+--------------------------------------------------+
| 1 | Link Aggregation Control Protocol(LACP) |
+---------------+--------------------------------------------------+
| 2 | Link Aggregation - Marker Protocol |
+---------------+--------------------------------------------------+
| 3 | Operations, Administration, and Maintenance(OAM) |
+---------------+--------------------------------------------------+
| 4 - 9 | Reserved for future use |
+---------------+--------------------------------------------------+
| 10 | Organization Specific Slow Protocol(OSSP) |
+---------------+--------------------------------------------------+
| 11 - 255 | Unused - Illegal values |
+---------------+--------------------------------------------------+
"""
_PACK_STR = '!B'
@classmethod
def parser(cls, buf):
(subtype, ) = struct.unpack_from(cls._PACK_STR, buf)
switch = {
SLOW_SUBTYPE_LACP: lacp,
# TODO: make parsers of other subtypes.
SLOW_SUBTYPE_MARKER: None,
SLOW_SUBTYPE_OAM: None,
SLOW_SUBTYPE_OSSP: None,
}
cls_ = switch.get(subtype)
if cls_:
return cls_.parser(buf)
else:
return None, None, buf
class lacp(packet_base.PacketBase):
"""Link Aggregation Control Protocol(LACP, IEEE 802.1AX)
header encoder/decoder class.
http://standards.ieee.org/getieee802/download/802.1AX-2008.pdf
LACPDU format
+------------------------------------------------+--------+
| LACPDU structure | Octets |
+================================================+========+
| Subtype = LACP | 1 |
+------------------------------------------------+--------+
| Version Number | 1 |
+------------+-----------------------------------+--------+
| TLV | TLV_type = Actor Information | 1 |
| Actor +-----------------------------------+--------+
| | Actor_Information_Length = 20 | 1 |
| +-----------------------------------+--------+
| | Actor_System_Priority | 2 |
| +-----------------------------------+--------+
| | Actor_System | 6 |
| +-----------------------------------+--------+
| | Actor_Key | 2 |
| +-----------------------------------+--------+
| | Actor_Port_Priority | 2 |
| +-----------------------------------+--------+
| | Actor_Port | 2 |
| +-----------------------------------+--------+
| | Actor_State | 1 |
| +-----------------------------------+--------+
| | Reserved | 3 |
+------------+-----------------------------------+--------+
| TLV | TLV_type = Partner Information | 1 |
| Partner +-----------------------------------+--------+
| | Partner_Information_Length = 20 | 1 |
| +-----------------------------------+--------+
| | Partner_System_Priority | 2 |
| +-----------------------------------+--------+
| | Partner_System | 6 |
| +-----------------------------------+--------+
| | Partner_Key | 2 |
| +-----------------------------------+--------+
| | Partner_Port_Priority | 2 |
| +-----------------------------------+--------+
| | Partner_Port | 2 |
| +-----------------------------------+--------+
| | Partner_State | 1 |
| +-----------------------------------+--------+
| | Reserved | 3 |
+------------+-----------------------------------+--------+
| TLV | TLV_type = Collector Information | 1 |
| Collector +-----------------------------------+--------+
| | Collector_Information_Length = 16 | 1 |
| +-----------------------------------+--------+
| | Collector_Max_Delay | 2 |
| +-----------------------------------+--------+
| | Reserved | 12 |
+------------+-----------------------------------+--------+
| TLV | TLV_type = Terminator | 1 |
| Terminator +-----------------------------------+--------+
| | Terminator_Length = 0 | 1 |
| +-----------------------------------+--------+
| | Reserved | 50 |
+------------+-----------------------------------+--------+
Terminator information uses a length value of 0 (0x00).
NOTE--The use of a Terminator_Length of 0 is intentional.
In TLV encoding schemes it is common practice
for the terminator encoding to be 0 both
for the type and the length.
Actor_State and Partner_State encoded as individual bits within
a single octet as follows:
+------+------+------+------+------+------+------+------+
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+======+======+======+======+======+======+======+======+
| EXPR | DFLT | DIST | CLCT | SYNC | AGGR | TMO | ACT |
+------+------+------+------+------+------+------+------+
ACT
bit 0.
about the activity control value with regard to this link.
TMO
bit 1.
about the timeout control value with regard to this link.
AGGR
bit 2.
about how the system regards this link from the point of view
of the aggregation.
SYNC
bit 3.
about how the system regards this link from the point of view
of the synchronization.
CLCT
bit 4.
about collecting of incoming frames.
DIST
bit 5.
about distributing of outgoing frames.
DFLT
bit 6.
about the opposite system information which the system use.
EXPR
bit 7.
about the expire state of the system.
An instance has the following attributes at least.
Most of them are same to the on-wire counterparts but in host byte
order.
__init__ takes the correspondig args in this order.
=============================== ====================================
Attribute Description
=============================== ====================================
version LACP version. This parameter must be
set to LACP_VERSION_NUMBER(i.e. 1).
actor_system_priority The priority assigned to this
System.
actor_system The Actor's System ID, encoded as
a MAC address.
actor_key The operational Key value assigned
to the port by the Actor.
actor_port_priority The priority assigned to this port.
actor_port The port number assigned to the
port by the Actor.
actor_state_activity .. _lacp_activity:
| about the activity control value
with regard to this link.
| LACP_STATE_ACTIVE(1)
| LACP_STATE_PASSIVE(0)
actor_state_timeout .. _lacp_timeout:
| about the timeout control value
with regard to this link.
| LACP_STATE_SHORT_TIMEOUT(1)
| LACP_STATE_LONG_TIMEOUT(0)
actor_state_aggregation .. _lacp_aggregation:
| about how the system regards this
link from the point of view of the
aggregation.
| LACP_STATE_AGGREGATEABLE(1)
| LACP_STATE_INDIVIDUAL(0)
actor_state_synchronization .. _lacp_synchronization:
| about how the system regards this
link from the point of view of the
synchronization.
| LACP_STATE_IN_SYNC(1)
| LACP_STATE_OUT_OF_SYNC(0)
actor_state_collecting .. _lacp_collecting:
| about collecting of incoming
frames.
| LACP_STATE_COLLECTING_ENABLED(1)
| LACP_STATE_COLLECTING_DISABLED(0)
actor_state_distributing .. _lacp_distributing:
| about distributing of outgoing
frames.
| LACP_STATE_DISTRIBUTING_ENABLED(1)
| LACP_STATE_DISTRIBUTING_DISABLED(0)
actor_state_defaulted .. _lacp_defaulted:
| about the Partner information
which the the Actor use.
| LACP_STATE_DEFAULTED_PARTNER(1)
| LACP_STATE_OPERATIONAL_PARTNER(0)
actor_state_expired .. _lacp_expired:
| about the state of the Actor.
| LACP_STATE_EXPIRED(1)
| LACP_STATE_NOT_EXPIRED(0)
partner_system_priority The priority assigned to the
Partner System.
partner_system The Partner's System ID, encoded
as a MAC address.
partner_key The operational Key value assigned
to the port by the Partner.
partner_port_priority The priority assigned to this port
by the Partner.
partner_port The port number assigned to the
port by the Partner.
partner_state_activity See :ref:`actor_state_activity\
<lacp_activity>`.
partner_state_timeout See :ref:`actor_state_timeout\
<lacp_timeout>`.
partner_state_aggregation See :ref:`actor_state_aggregation\
<lacp_aggregation>`.
partner_state_synchronization See
:ref:`actor_state_synchronization\
<lacp_synchronization>`.
partner_state_collecting See :ref:`actor_state_collecting\
<lacp_collecting>`.
partner_state_distributing See :ref:`actor_state_distributing\
<lacp_distributing>`.
partner_state_defaulted See :ref:`actor_state_defaulted\
<lacp_defaulted>`.
partner_state_expired See :ref:`actor_state_expired\
<lacp_expired>`.
collector_max_delay the maximum time that the Frame
Collector may delay.
=============================== ====================================
"""
LACP_VERSION_NUMBER = 1
# LACP TLV type
LACP_TLV_TYPE_ACTOR = 1
LACP_TLV_TYPE_PARTNER = 2
LACP_TLV_TYPE_COLLECTOR = 3
LACP_TLV_TYPE_TERMINATOR = 0
# LACP state(LACP_Activity)
LACP_STATE_ACTIVE = 1
LACP_STATE_PASSIVE = 0
# LACP state(LACP_Timeout)
LACP_STATE_SHORT_TIMEOUT = 1
LACP_STATE_LONG_TIMEOUT = 0
# LACP state(Aggregation)
LACP_STATE_AGGREGATEABLE = 1
LACP_STATE_INDIVIDUAL = 0
# LACP state(Synchronization)
LACP_STATE_IN_SYNC = 1
LACP_STATE_OUT_OF_SYNC = 0
# LACP state(Collecting)
LACP_STATE_COLLECTING_ENABLED = 1
LACP_STATE_COLELCTING_DISABLED = 0
# LACP state(Distributing)
LACP_STATE_DISTRIBUTING_ENABLED = 1
LACP_STATE_DISTRIBUTING_DISABLED = 0
# LACP state(Defaulted)
LACP_STATE_DEFAULED_PARTNER = 1
LACP_STATE_OPERATIONAL_PARTNER = 0
# LACP state(Expired)
LACP_STATE_EXPIRED = 1
LACP_STATE_NOT_EXPIRED = 0
# The number of seconds between periodic transmissions using
# Short Timeouts.
FAST_PERIODIC_TIME = 1
# The number of seconds between periodic transmissions using
# Long Timeouts.
SLOW_PERIODIC_TIME = 30
# The number of seconds before invalidating received LACPDU
# information when using Short Timeouts(3 x Fast_Periodic_Time).
SHORT_TIMEOUT_TIME = 3 * FAST_PERIODIC_TIME
# The number of seconds before invalidating received LACPDU
# information when using Long Timeouts (3 x Slow_Periodic_Time).
LONG_TIMEOUT_TIME = 3 * SLOW_PERIODIC_TIME
_HLEN_PACK_STR = '!BB'
_HLEN_PACK_LEN = struct.calcsize(_HLEN_PACK_STR)
_ACTPRT_INFO_PACK_STR = '!BBH6sHHHB3x'
_ACTPRT_INFO_PACK_LEN = struct.calcsize(_ACTPRT_INFO_PACK_STR)
_COL_INFO_PACK_STR = '!BBH12x'
_COL_INFO_PACK_LEN = struct.calcsize(_COL_INFO_PACK_STR)
_TRM_PACK_STR = '!BB50x'
_TRM_PACK_LEN = struct.calcsize(_TRM_PACK_STR)
_ALL_PACK_LEN = _HLEN_PACK_LEN + _ACTPRT_INFO_PACK_LEN * 2 + \
_COL_INFO_PACK_LEN + _TRM_PACK_LEN
def __init__(self, version=LACP_VERSION_NUMBER,
actor_system_priority=0,
actor_system=mac.haddr_to_bin('00:00:00:00:00:00'),
actor_key=0, actor_port_priority=0, actor_port=0,
actor_state_activity=0, actor_state_timeout=0,
actor_state_aggregation=0,
actor_state_synchronization=0,
actor_state_collecting=0, actor_state_distributing=0,
actor_state_defaulted=0, actor_state_expired=0,
partner_system_priority=0,
partner_system=mac.haddr_to_bin('00:00:00:00:00:00'),
partner_key=0, partner_port_priority=0, partner_port=0,
partner_state_activity=0, partner_state_timeout=0,
partner_state_aggregation=0,
partner_state_synchronization=0,
partner_state_collecting=0,
partner_state_distributing=0,
partner_state_defaulted=0, partner_state_expired=0,
collector_max_delay=0):
super(lacp, self).__init__()
# parameter check
assert (1 == actor_state_activity | 1)
assert (1 == actor_state_timeout | 1)
assert (1 == actor_state_aggregation | 1)
assert (1 == actor_state_synchronization | 1)
assert (1 == actor_state_collecting | 1)
assert (1 == actor_state_distributing | 1)
assert (1 == actor_state_defaulted | 1)
assert (1 == actor_state_expired | 1)
assert (1 == partner_state_activity | 1)
assert (1 == partner_state_timeout | 1)
assert (1 == partner_state_aggregation | 1)
assert (1 == partner_state_synchronization | 1)
assert (1 == partner_state_collecting | 1)
assert (1 == partner_state_distributing | 1)
assert (1 == partner_state_defaulted | 1)
assert (1 == partner_state_expired | 1)
#------------------------------
# Header
#------------------------------
self.subtype = SLOW_SUBTYPE_LACP
self.version = version
#------------------------------
# Actor Information
#------------------------------
self.actor_tag = self.LACP_TLV_TYPE_ACTOR
self.actor_length = self._ACTPRT_INFO_PACK_LEN
self.actor_system_priority = actor_system_priority
self.actor_system = actor_system
self.actor_key = actor_key
self.actor_port_priority = actor_port_priority
self.actor_port = actor_port
self.actor_state_activity = actor_state_activity
self.actor_state_timeout = actor_state_timeout
self.actor_state_aggregation = actor_state_aggregation
self.actor_state_synchronization = actor_state_synchronization
self.actor_state_collecting = actor_state_collecting
self.actor_state_distributing = actor_state_distributing
self.actor_state_defaulted = actor_state_defaulted
self.actor_state_expired = actor_state_expired
self.actor_state = (
(self.actor_state_activity << 0) |
(self.actor_state_timeout << 1) |
(self.actor_state_aggregation << 2) |
(self.actor_state_synchronization << 3) |
(self.actor_state_collecting << 4) |
(self.actor_state_distributing << 5) |
(self.actor_state_defaulted << 6) |
(self.actor_state_expired << 7))
#------------------------------
# Partner Information
#------------------------------
self.partner_tag = self.LACP_TLV_TYPE_PARTNER
self.partner_length = self._ACTPRT_INFO_PACK_LEN
self.partner_system_priority = partner_system_priority
self.partner_system = partner_system
self.partner_key = partner_key
self.partner_port_priority = partner_port_priority
self.partner_port = partner_port
self.partner_state_activity = partner_state_activity
self.partner_state_timeout = partner_state_timeout
self.partner_state_aggregation = partner_state_aggregation
self.partner_state_synchronization = \
partner_state_synchronization
self.partner_state_collecting = partner_state_collecting
self.partner_state_distributing = partner_state_distributing
self.partner_state_defaulted = partner_state_defaulted
self.partner_state_expired = partner_state_expired
self.partner_state = (
(self.partner_state_activity << 0) |
(self.partner_state_timeout << 1) |
(self.partner_state_aggregation << 2) |
(self.partner_state_synchronization << 3) |
(self.partner_state_collecting << 4) |
(self.partner_state_distributing << 5) |
(self.partner_state_defaulted << 6) |
(self.partner_state_expired << 7))
#------------------------------
# Collector Information
#------------------------------
self.collector_tag = self.LACP_TLV_TYPE_COLLECTOR
self.collector_length = self._COL_INFO_PACK_LEN
self.collector_max_delay = collector_max_delay
#------------------------------
# Terminator
#------------------------------
self.terminator_tag = self.LACP_TLV_TYPE_TERMINATOR
self.terminator_length = 0
@classmethod
def parser(cls, buf):
assert cls._ALL_PACK_LEN == len(buf)
offset = 0
#------------------------------
# Header
#------------------------------
(subtype, version
) = struct.unpack_from(cls._HLEN_PACK_STR, buf, offset)
assert SLOW_SUBTYPE_LACP == subtype
assert cls.LACP_VERSION_NUMBER == version
offset += cls._HLEN_PACK_LEN
#------------------------------
# Actor Information
#------------------------------
(actor_tag, actor_length, actor_system_priority, actor_system,
actor_key, actor_port_priority, actor_port, actor_state
) = struct.unpack_from(cls._ACTPRT_INFO_PACK_STR, buf, offset)
assert cls.LACP_TLV_TYPE_ACTOR == actor_tag
assert cls._ACTPRT_INFO_PACK_LEN == actor_length
offset += cls._ACTPRT_INFO_PACK_LEN
actor_state_activity = (actor_state >> 0) & 1
actor_state_timeout = (actor_state >> 1) & 1
actor_state_aggregation = (actor_state >> 2) & 1
actor_state_synchronization = (actor_state >> 3) & 1
actor_state_collecting = (actor_state >> 4) & 1
actor_state_distributing = (actor_state >> 5) & 1
actor_state_defaulted = (actor_state >> 6) & 1
actor_state_expired = (actor_state >> 7) & 1
#------------------------------
# Partner Information
#------------------------------
(partner_tag, partner_length, partner_system_priority,
partner_system, partner_key, partner_port_priority,
partner_port, partner_state
) = struct.unpack_from(cls._ACTPRT_INFO_PACK_STR, buf, offset)
assert cls.LACP_TLV_TYPE_PARTNER == partner_tag
assert cls._ACTPRT_INFO_PACK_LEN == partner_length
offset += cls._ACTPRT_INFO_PACK_LEN
partner_state_activity = (partner_state >> 0) & 1
partner_state_timeout = (partner_state >> 1) & 1
partner_state_aggregation = (partner_state >> 2) & 1
partner_state_synchronization = (partner_state >> 3) & 1
partner_state_collecting = (partner_state >> 4) & 1
partner_state_distributing = (partner_state >> 5) & 1
partner_state_defaulted = (partner_state >> 6) & 1
partner_state_expired = (partner_state >> 7) & 1
#------------------------------
# Collector Information
#------------------------------
(collector_tag, collector_length, collector_max_delay
) = struct.unpack_from(cls._COL_INFO_PACK_STR, buf, offset)
assert cls.LACP_TLV_TYPE_COLLECTOR == collector_tag
assert cls._COL_INFO_PACK_LEN == collector_length
offset += cls._COL_INFO_PACK_LEN
#------------------------------
# Terminator Information
#------------------------------
(terminator_tag, terminator_length
) = struct.unpack_from(cls._TRM_PACK_STR, buf, offset)
assert cls.LACP_TLV_TYPE_TERMINATOR == terminator_tag
assert 0 == terminator_length
return cls(version, actor_system_priority,
actor_system, actor_key, actor_port_priority,
actor_port, actor_state_activity,
actor_state_timeout, actor_state_aggregation,
actor_state_synchronization, actor_state_collecting,
actor_state_distributing, actor_state_defaulted,
actor_state_expired, partner_system_priority,
partner_system, partner_key, partner_port_priority,
partner_port, partner_state_activity,
partner_state_timeout, partner_state_aggregation,
partner_state_synchronization,
partner_state_collecting, partner_state_distributing,
partner_state_defaulted, partner_state_expired,
collector_max_delay), None, buf[lacp._ALL_PACK_LEN:]
def serialize(self, payload, prev):
header = struct.pack(self._HLEN_PACK_STR, self.subtype,
self.version)
actor = struct.pack(self._ACTPRT_INFO_PACK_STR,
self.actor_tag, self.actor_length,
self.actor_system_priority,
self.actor_system, self.actor_key,
self.actor_port_priority, self.actor_port,
self.actor_state)
partner = struct.pack(self._ACTPRT_INFO_PACK_STR,
self.partner_tag, self.partner_length,
self.partner_system_priority,
self.partner_system, self.partner_key,
self.partner_port_priority,
self.partner_port, self.partner_state)
collector = struct.pack(self._COL_INFO_PACK_STR,
self.collector_tag,
self.collector_length,
self.collector_max_delay)
terminator = struct.pack(self._TRM_PACK_STR,
self.terminator_tag,
self.terminator_length)
return header + actor + partner + collector + terminator

View File

@ -19,6 +19,7 @@ from . import arp
from . import ipv4 from . import ipv4
from . import ipv6 from . import ipv6
from . import lldp from . import lldp
from . import slow
from ryu.ofproto import ether from ryu.ofproto import ether
from ryu.ofproto.ofproto_parser import msg_pack_into from ryu.ofproto.ofproto_parser import msg_pack_into
@ -67,3 +68,4 @@ vlan.register_packet_type(arp.arp, ether.ETH_TYPE_ARP)
vlan.register_packet_type(ipv4.ipv4, ether.ETH_TYPE_IP) vlan.register_packet_type(ipv4.ipv4, ether.ETH_TYPE_IP)
vlan.register_packet_type(ipv6.ipv6, ether.ETH_TYPE_IPV6) vlan.register_packet_type(ipv6.ipv6, ether.ETH_TYPE_IPV6)
vlan.register_packet_type(lldp.lldp, ether.ETH_TYPE_LLDP) vlan.register_packet_type(lldp.lldp, ether.ETH_TYPE_LLDP)
vlan.register_packet_type(slow.slow, ether.ETH_TYPE_SLOW)

1096
ryu/tests/unit/packet/test_slow.py Executable file

File diff suppressed because it is too large Load Diff