Merge branch 'master' into patch-1

This commit is contained in:
Josh Bailey 2021-02-01 09:13:50 +13:00 committed by GitHub
commit f3316fa85a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 1835 additions and 701 deletions

25
.github/workflows/tests-unit.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Unit tests
on: [push, pull_request]
jobs:
unit-tests:
name: Unit tests
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions coveralls
bash ryu/tests/integrated/common/install_docker_test_pkg_for_github_actions.sh
- name: Test with tox
run: NOSE_VERBOSE=0 tox

11
.readthedocs.yml Normal file
View File

@ -0,0 +1,11 @@
version: 2
build:
image: latest
python:
version: 3.6
install:
- method: pip
path: .
sphinx:
configuration: doc/source/conf.py
formats: all

15
.renovaterc.json Normal file
View File

@ -0,0 +1,15 @@
{
"separateMajorMinor": false,
"schedule": [
"after 10pm every weekday",
"before 5am every weekday",
"every weekend"
],
"timezone": "Pacific/Auckland",
"extends": [
"config:base",
":prHourlyLimit1",
":preserveSemverRanges",
"docker:enableMajor"
]
}

9
.stickler.yml Normal file
View File

@ -0,0 +1,9 @@
---
linters:
flake8:
python: 3
max-line-length: 120
pep8:
python: 3
max-line-length: 120
py3k:

View File

@ -1,26 +0,0 @@
language: python
python:
- "3.5" # Python 3.5 still needs to be installed on Travis-CI
env:
- TOX_ENV=py27
- TOX_ENV=py34
- TOX_ENV=py35
- TOX_ENV=pypy26
- TOX_ENV=pycodestyle
- TOX_ENV=autopep8
services:
- docker
sudo: required # Required to enable Docker service
install:
- pip install tox coveralls
- bash ryu/tests/integrated/common/install_docker_test_pkg_for_travis.sh
script:
- NOSE_VERBOSE=0 tox -e $TOX_ENV
after_success:
- coveralls

View File

@ -5,20 +5,8 @@ How to Get Your Change Into Ryu
Submitting a change
===================
Send patches to ryu-devel@lists.sourceforge.net. Please don't use "Pull
Request" on GitHub. We expect you to send patches in "git-format-patch"
style.
.. code-block:: bash
# "N" means the number of commits to be included
$ git format-patch -s HEAD~N
# To add cover (e.g., [PATCH 0/X]), specify "--cover-letter" option
$ git format-patch -s --cover-letter HEAD~N
# You can send patches by "git send-email" command
$ git send-email --to="ryu-devel@lists.sourceforge.net" *.patch
To send patches to ryu, please make a
`pull request <https://github.com/faucetsdn/ryu>`_ on GitHub.
Please check your changes with autopep8, pycodestyle(pep8) and running
unit tests to make sure that they don't break the existing features.
@ -42,9 +30,9 @@ features (it's not a must though).
Python version and libraries
============================
* Python 2.7, 3.4, 3.5:
* Python 3.5, 3.6, 3.7, 3.8, 3.9:
Ryu supports multiple Python version. CI tests on Travis-CI is running
Ryu supports multiple Python versions. CI tests on GitHub Actions is running
on these versions.
* standard library + widely used library:

View File

@ -2,7 +2,7 @@ What's Ryu
==========
Ryu is a component-based software defined networking framework.
Ryu provides software components with well defined API that make it
Ryu provides software components with well defined API's that make it
easy for developers to create new network management and control
applications. Ryu supports various protocols for managing network
devices, such as OpenFlow, Netconf, OF-config, etc. About OpenFlow,
@ -20,7 +20,7 @@ Installing Ryu is quite easy::
If you prefer to install Ryu from the source code::
% git clone git://github.com/osrg/ryu.git
% git clone https://github.com/faucetsdn/ryu.git
% cd ryu; pip install .
If you want to write your Ryu application, have a look at
@ -33,14 +33,14 @@ After writing your application, just type::
Optional Requirements
=====================
Some functionalities of ryu requires extra packages:
Some functions of ryu require extra packages:
- OF-Config requires lxml and ncclient
- NETCONF requires paramiko
- BGP speaker (SSH console) requires paramiko
- Zebra protocol service (database) requires SQLAlchemy
If you want to use the functionalities, please install requirements::
If you want to use these functions, please install the requirements::
% pip install -r tools/optional-requires
@ -49,8 +49,8 @@ Please refer to tools/optional-requires for details.
Prerequisites
=============
If you got some error messages at installation step, please confirm
dependencies for building required Python packages.
If you got some error messages at the installation stage, please confirm
dependencies for building the required Python packages.
On Ubuntu(16.04 LTS or later)::
@ -59,7 +59,7 @@ On Ubuntu(16.04 LTS or later)::
Support
=======
Ryu Official site is `<http://osrg.github.io/ryu/>`_.
Ryu Official site is `<https://ryu-sdn.org/>`_.
If you have any
questions, suggestions, and patches, the mailing list is available at

10
debian/control vendored
View File

@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 9.0.0), python-all (>= 2.6), python-sphinx
Build-Depends-Indep:
python-eventlet,
python-lxml,
python-msgpack (>= 0.3.0),
python-msgpack (>= 0.4.0),
python-netaddr,
python-oslo.config (>= 1:1.2.0),
python-paramiko,
@ -17,9 +17,9 @@ Build-Depends-Indep:
python-pip,
python-pbr
Standards-Version: 3.9.5
Homepage: http://osrg.github.io/ryu/
Vcs-Git: git://github.com/osrg/ryu.git
Vcs-Browser: http://github.com/osrg/ryu
Homepage: https://ryu-sdn.org
Vcs-Git: git://github.com/faucetsdn/ryu.git
Vcs-Browser: https://github.com/faucetsdn/ryu
XS-Python-Version: >= 2.6
Package: python-ryu
@ -28,7 +28,7 @@ Section: python
Depends:
python-eventlet,
python-lxml,
python-msgpack (>= 0.3.0),
python-msgpack (>= 0.4.0),
python-netaddr,
python-oslo.config (>= 1:1.2.0),
python-paramiko,

2
debian/copyright vendored
View File

@ -1,6 +1,6 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: ryu
Source: http://github.com/osrg/ryu
Source: http://github.com/faucetsdn/ryu
Files: *
Copyright: 2014 Ryu Project Team <ryu-devel@lists.sourceforge.net>

View File

@ -12,3 +12,4 @@ Others provide some functionalities to other Ryu applications.
app/ofctl.rst
app/ofctl_rest.rst
app/rest_vtep.rst
app/bgp_application.rst

View File

@ -0,0 +1,6 @@
**************************************
ryu.services.protocols.bgp.application
**************************************
.. automodule:: ryu.services.protocols.bgp.application
:members:

View File

@ -15,3 +15,4 @@ Ryu provides some useful library for your network applications.
library_bgp_speaker_ref.rst
library_mrt.rst
library_ovsdb_manager.rst
library_ovsdb.rst

View File

@ -0,0 +1,76 @@
*************
OVSDB library
*************
Path: ``ryu.lib.ovs``
Similar to the :doc:`library_ovsdb_manager`, this library enables your
application to speak the OVSDB protocol (RFC7047_), but differ from the
:doc:`library_ovsdb_manager`, this library will initiate connections from
controller side as ovs-vsctl_ command does.
Please make sure that your devices are listening on either the Unix domain
socket or TCP/SSL port before calling the APIs of this library.
.. code-block:: bash
# Show current configuration
$ ovs-vsctl get-manager
# Set TCP listen address
$ ovs-vsctl set-manager "ptcp:6640"
See manpage of ovs-vsctl_ command for more details.
.. _RFC7047: https://tools.ietf.org/html/rfc7047
.. _ovs-vsctl: http://openvswitch.org/support/dist-docs/ovs-vsctl.8.txt
Basic Usage
===========
1. Instantiate :py:mod:`ryu.lib.ovs.vsctl.VSCtl`.
2. Construct commands with :py:mod:`ryu.lib.ovs.vsctl.VSCtlCommand`.
The syntax is almost the same as ovs-vsctl_ command.
3. Execute commands via :py:mod:`ryu.lib.ovs.vsctl.VSCtl.run_command`.
Example
-------
.. code-block:: python
from ryu.lib.ovs import vsctl
OVSDB_ADDR = 'tcp:127.0.0.1:6640'
ovs_vsctl = vsctl.VSCtl(OVSDB_ADDR)
# Equivalent to
# $ ovs-vsctl show
command = vsctl.VSCtlCommand('show')
ovs_vsctl.run_command([command])
print(command)
# >>> VSCtlCommand(args=[],command='show',options=[],result='830d781f-c3c8-4b4f-837e-106e1b33d058\n ovs_version: "2.8.90"\n')
# Equivalent to
# $ ovs-vsctl list Port s1-eth1
command = vsctl.VSCtlCommand('list', ('Port', 's1-eth1'))
ovs_vsctl.run_command([command])
print(command)
# >>> VSCtlCommand(args=('Port', 's1-eth1'),command='list',options=[],result=[<ovs.db.idl.Row object at 0x7f525fb682e8>])
print(command.result[0].name)
# >>> s1-eth1
API Reference
=============
ryu.lib.ovs.vsctl
-----------------
.. automodule:: ryu.lib.ovs.vsctl
:members:
ryu.lib.ovs.bridge
------------------
.. automodule:: ryu.lib.ovs.bridge
:members:

View File

@ -54,6 +54,7 @@ The followings shows the supported NXAction classes in OpenFlow1.0 or later
.. autoclass:: NXActionCT
.. autoclass:: NXActionNAT
.. autoclass:: NXActionOutputTrunc
.. autoclass:: NXActionDecNshTtl
.. autoclass:: NXFlowSpecMatch
.. autoclass:: NXFlowSpecLoad
.. autoclass:: NXFlowSpecOutput

View File

@ -19,7 +19,7 @@ The test procedure
* run LINC switch
* run Ryu test_of_config app
For getting/installing Ryu itself, please refer to http://osrg.github.io/ryu/
For getting/installing Ryu itself, please refer to https://ryu-sdn.org/
Install Erlang environment

View File

@ -14,7 +14,7 @@ Using Ryu Network Operating System with OpenStack as OpenFlow controller
Ryu cooperates with OpenStack using Quantum Ryu plugin. The plugin is
available in the official Quantum releases.
For more information, please visit http://github.com/osrg/ryu/wiki/OpenStack .
For more information, please visit https://github.com/faucetsdn/ryu/wiki/OpenStack .
We described instructions of the installation / configuration of OpenStack
with Ryu, and we provide pre-configured VM image to be able to easily try
OpenStack with Ryu.

View File

@ -5,21 +5,21 @@ The First Application
Whetting Your Appetite
======================
If you want to manage the network gears (switches, routers, etc) at
your way, you need to write your Ryu application. Your application
tells Ryu how you want to manage the gears. Then Ryu configures the
gears by using OpenFlow protocol, etc.
If you want to manage network gear (switches, routers, etc) your
own way, you just need to write your own Ryu application. Your application
tells Ryu how you want to manage the gear. Then Ryu configures the
gear by using OpenFlow protocol, etc.
Writing Ryu application is easy. It's just Python scripts.
Writing Ryu applications is easy. They're just Python scripts.
Start Writing
=============
We show a Ryu application that make OpenFlow switches work as a dumb
Here we show a Ryu application that makes an OpenFlow switch work as a dumb
layer 2 switch.
Open a text editor creating a new file with the following content:
Open a text editor and create a new file with the following content:
.. code-block:: python
@ -29,9 +29,9 @@ Open a text editor creating a new file with the following content:
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
Ryu application is just a Python script so you can save the file with
any name, extensions, and any place you want. Let's name the file
'l2.py' at your home directory.
Ryu applications are just Python scripts so you can save the file with
any name, any extension, and any place you want. Let's name the file
'l2.py' in your home directory.
This application does nothing useful yet, however it's a complete Ryu
application. In fact, you can run this Ryu application::
@ -44,7 +44,7 @@ application. In fact, you can run this Ryu application::
All you have to do is define a new subclass of RyuApp to run
your Python script as a Ryu application.
Next let's add the functionality of sending a received packet to all
Next let's add some functionality that sends a received packet to all
the ports.
.. code-block:: python
@ -75,18 +75,18 @@ the ports.
dp.send_msg(out)
A new method 'packet_in_handler' is added to L2Switch class. This is
called when Ryu receives an OpenFlow packet_in message. The trick is
A new method 'packet_in_handler' is added to the L2Switch class. This is
called when Ryu receives an OpenFlow packet_in message. The trick is the
'set_ev_cls' decorator. This decorator tells Ryu when the decorated
function should be called.
The first argument of the decorator indicates an event that makes
function called. As you expect easily, every time Ryu gets a
The first argument of the decorator indicates which type of event this
function should be called for. As you might expect, every time Ryu gets a
packet_in message, this function is called.
The second argument indicates the state of the switch. Probably, you
The second argument indicates the state of the switch. You probably
want to ignore packet_in messages before the negotiation between Ryu
and the switch finishes. Using 'MAIN_DISPATCHER' as the second
and the switch is finished. Using 'MAIN_DISPATCHER' as the second
argument means this function is called only after the negotiation
completes.
@ -103,24 +103,24 @@ Ready for the second half.
* OFPActionOutput class is used with a packet_out message to specify a
switch port that you want to send the packet out of. This
application need a switch to send out of all the ports so OFPP_FLOOD
constant is used.
application uses the OFPP_FLOOD flag to indicate that the packet should
be sent out on all ports.
* OFPPacketOut class is used to build a packet_out message.
* If you call Datapath class's send_msg method with a OpenFlow message
class object, Ryu builds and send the on-wire data format to the switch.
class object, Ryu builds and sends the on-wire data format to the switch.
Here, you finished implementing your first Ryu application. You are ready to
run this Ryu application that does something useful.
There, you finished implementing your first Ryu application. You are ready to
run a Ryu application that does something useful.
A dumb l2 switch is too dumb? You want to implement a learning l2
Is a dumb L2 switch is too dumb? You want to implement a learning L2
switch? Move to `the next step
<https://github.com/osrg/ryu/blob/master/ryu/app/simple_switch.py>`_. You
<https://github.com/faucetsdn/ryu/blob/master/ryu/app/simple_switch.py>`_. You
can learn from the existing Ryu applications at `ryu/app
<https://github.com/osrg/ryu/blob/master/ryu/app/>`_ directory and
<https://github.com/faucetsdn/ryu/blob/master/ryu/app/>`_ directory and
`integrated tests
<https://github.com/osrg/ryu/blob/master/ryu/tests/integrated/>`_
<https://github.com/faucetsdn/ryu/blob/master/ryu/tests/integrated/>`_
directory.

View File

@ -14,5 +14,5 @@
# limitations under the License.
version_info = (4, 21)
version_info = (4, 34)
version = '.'.join(map(str, version_info))

View File

@ -56,7 +56,7 @@ class GUIServerController(ControllerBase):
path = "%s/html/" % PATH
self.static_app = DirectoryApp(path)
@route('topology', '/{filename:.*}')
@route('topology', '/{filename:[^/]*}')
def static_handler(self, req, **kwargs):
if kwargs['filename']:
req.path_info = kwargs['filename']

View File

@ -16,22 +16,37 @@
# client for ryu.app.ofctl.service
import numbers
from ryu.base import app_manager
from . import event
def get_datapath(app, dpid):
def get_datapath(app, dpid=None):
"""
Get datapath object by dpid.
:param app: Client RyuApp instance
:param dpid: Datapath-id (in integer)
:param dpid: Datapath ID (int type) or None to get all datapath objects
Returns None on error.
Returns a object of datapath, a list of datapath objects when no dpid
given or None when error.
Raises an exception if any of the given values is invalid.
Example::
# ...(snip)...
import ryu.app.ofctl.api as ofctl_api
class MyApp(app_manager.RyuApp):
def _my_handler(self, ev):
# Get all datapath objects
result = ofctl_api.get_datapath(self)
# Get the datapath object which has the given dpid
result = ofctl_api.get_datapath(self, dpid=1)
"""
assert isinstance(dpid, numbers.Integral)
return app.send_request(event.GetDatapathRequest(dpid=dpid))()
@ -55,12 +70,19 @@ def send_msg(app, msg, reply_cls=None, reply_multi=False):
Example::
import ryu.app.ofctl.api as api
# ...(snip)...
import ryu.app.ofctl.api as ofctl_api
msg = parser.OFPPortDescStatsRequest(datapath=datapath)
result = api.send_msg(self, msg,
reply_cls=parser.OFPPortDescStatsReply,
reply_multi=True)
class MyApp(app_manager.RyuApp):
def _my_handler(self, ev):
# ...(snip)...
msg = parser.OFPPortDescStatsRequest(datapath=datapath)
result = ofctl_api.send_msg(
self, msg,
reply_cls=parser.OFPPortDescStatsReply,
reply_multi=True)
"""
return app.send_request(event.SendMsgRequest(msg=msg,
reply_cls=reply_cls,

View File

@ -33,8 +33,8 @@ class _ReplyBase(event.EventReplyBase):
# get datapath
class GetDatapathRequest(_RequestBase):
def __init__(self, dpid):
assert isinstance(dpid, numbers.Integral)
def __init__(self, dpid=None):
assert dpid is None or isinstance(dpid, numbers.Integral)
super(GetDatapathRequest, self).__init__()
self.dpid = dpid

View File

@ -64,6 +64,22 @@ class OfctlService(app_manager.RyuApp):
self.unobserve_event(ev_cls)
self.logger.debug('ofctl: stop observing %s', ev_cls)
def _cancel(self, info, barrier_xid, exception):
xid = info.barriers.pop(barrier_xid)
req = info.xids.pop(xid)
msg = req.msg
datapath = msg.datapath
parser = datapath.ofproto_parser
is_barrier = isinstance(msg, parser.OFPBarrierRequest)
info.results.pop(xid)
if not is_barrier and req.reply_cls is not None:
self._unobserve_msg(req.reply_cls)
self.logger.error('failed to send message <%s>', req.msg)
self.reply_to_request(req, event.Reply(exception=exception))
@staticmethod
def _is_error(msg):
return (ofp_event.ofp_msg_to_ev_cls(type(msg)) ==
@ -81,6 +97,9 @@ class OfctlService(app_manager.RyuApp):
self._switches[id] = new_info
if old_info:
old_info.datapath.close()
for xid in list(old_info.barriers):
self._cancel(
old_info, xid, exception.InvalidDatapath(result=id))
@set_ev_cls(ofp_event.EventOFPStateChange, DEAD_DISPATCHER)
def _handle_dead(self, ev):
@ -96,24 +115,25 @@ class OfctlService(app_manager.RyuApp):
if info.datapath is datapath:
self.logger.debug('forget info %s', info)
self._switches.pop(id)
for xid in list(info.barriers):
self._cancel(info, xid, exception.InvalidDatapath(result=id))
@set_ev_cls(event.GetDatapathRequest, MAIN_DISPATCHER)
def _handle_get_datapath(self, req):
id = req.dpid
assert isinstance(id, numbers.Integral)
try:
datapath = self._switches[id].datapath
except KeyError:
datapath = None
self.logger.debug('dpid %s -> datapath %s', id, datapath)
rep = event.Reply(result=datapath)
self.reply_to_request(req, rep)
result = None
if req.dpid is None:
result = [v.datapath for v in self._switches.values()]
else:
if req.dpid in self._switches:
result = self._switches[req.dpid].datapath
self.reply_to_request(req, event.Reply(result=result))
@set_ev_cls(event.SendMsgRequest, MAIN_DISPATCHER)
def _handle_send_msg(self, req):
msg = req.msg
datapath = msg.datapath
parser = datapath.ofproto_parser
is_barrier = isinstance(msg, parser.OFPBarrierRequest)
try:
si = self._switches[datapath.id]
@ -132,7 +152,7 @@ class OfctlService(app_manager.RyuApp):
si.xids[xid] = req
si.barriers[barrier_xid] = xid
if isinstance(req.msg, parser.OFPBarrierRequest):
if is_barrier:
barrier = msg
datapath.set_xid(barrier)
_store_xid(barrier.xid, barrier.xid)
@ -143,9 +163,15 @@ class OfctlService(app_manager.RyuApp):
barrier = datapath.ofproto_parser.OFPBarrierRequest(datapath)
datapath.set_xid(barrier)
_store_xid(msg.xid, barrier.xid)
datapath.send_msg(msg)
if not datapath.send_msg(msg):
return self._cancel(
si, barrier.xid,
exception.InvalidDatapath(result=datapath.id))
datapath.send_msg(barrier)
if not datapath.send_msg(barrier):
return self._cancel(
si, barrier.xid,
exception.InvalidDatapath(result=datapath.id))
@set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
def _handle_barrier(self, ev):

View File

@ -1147,13 +1147,13 @@ class Action(object):
if REST_ACTION in flow:
actions = []
for act in flow[REST_ACTION]:
field_value = re.search('SET_FIELD: \{ip_dscp:(\d+)', act)
field_value = re.search(r'SET_FIELD: \{ip_dscp:(\d+)', act)
if field_value:
actions.append({REST_ACTION_MARK: field_value.group(1)})
meter_value = re.search('METER:(\d+)', act)
meter_value = re.search(r'METER:(\d+)', act)
if meter_value:
actions.append({REST_ACTION_METER: meter_value.group(1)})
queue_value = re.search('SET_QUEUE:(\d+)', act)
queue_value = re.search(r'SET_QUEUE:(\d+)', act)
if queue_value:
actions.append({REST_ACTION_QUEUE: queue_value.group(1)})
action = {REST_ACTION: actions}

View File

@ -85,7 +85,7 @@ class SimpleSwitch13(app_manager.RyuApp):
dst = eth.dst
src = eth.src
dpid = datapath.id
dpid = format(datapath.id, "d").zfill(16)
self.mac_to_port.setdefault(dpid, {})
self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port)

View File

@ -85,21 +85,21 @@ class SimpleSwitchController(ControllerBase):
def list_mac_table(self, req, **kwargs):
simple_switch = self.simple_switch_app
dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
dpid = kwargs['dpid']
if dpid not in simple_switch.mac_to_port:
return Response(status=404)
mac_table = simple_switch.mac_to_port.get(dpid, {})
body = json.dumps(mac_table)
return Response(content_type='application/json', body=body)
return Response(content_type='application/json', text=body)
@route('simpleswitch', url, methods=['PUT'],
requirements={'dpid': dpid_lib.DPID_PATTERN})
def put_mac_table(self, req, **kwargs):
simple_switch = self.simple_switch_app
dpid = dpid_lib.str_to_dpid(kwargs['dpid'])
dpid = kwargs['dpid']
try:
new_entry = req.json if req.body else {}
except ValueError:
@ -111,6 +111,6 @@ class SimpleSwitchController(ControllerBase):
try:
mac_table = simple_switch.set_mac_to_port(dpid, new_entry)
body = json.dumps(mac_table)
return Response(content_type='application/json', body=body)
return Response(content_type='application/json', text=body)
except Exception as e:
return Response(status=500)

View File

@ -23,15 +23,17 @@ The main component of OpenFlow controller.
"""
import contextlib
from ryu import cfg
import logging
import random
from socket import IPPROTO_TCP
from socket import TCP_NODELAY
from socket import SHUT_WR
from socket import timeout as SocketTimeout
import ssl
from ryu import cfg
from ryu.lib import hub
from ryu.lib.hub import StreamServer
import random
import ssl
from socket import IPPROTO_TCP, TCP_NODELAY, SHUT_RDWR, timeout as SocketTimeout
import netaddr
import ryu.base.app_manager
@ -65,6 +67,7 @@ CONF.register_cli_opts([
cfg.StrOpt('ctl-privkey', default=None, help='controller private key'),
cfg.StrOpt('ctl-cert', default=None, help='controller certificate'),
cfg.StrOpt('ca-certs', default=None, help='CA certificates'),
cfg.StrOpt('ciphers', default=None, help='list of ciphers to enable'),
cfg.ListOpt('ofp-switch-address-list', item_type=str, default=[],
help='list of IP address and port pairs (default empty). '
'e.g., "127.0.0.1:6653,[::1]:6653"'),
@ -163,6 +166,26 @@ class OpenFlowController(object):
def server_loop(self, ofp_tcp_listen_port, ofp_ssl_listen_port):
if CONF.ctl_privkey is not None and CONF.ctl_cert is not None:
if not hasattr(ssl, 'SSLContext'):
# anything less than python 2.7.9 supports only TLSv1
# or less, thus we choose TLSv1
ssl_args = {'ssl_version': ssl.PROTOCOL_TLSv1}
else:
# from 2.7.9 and versions 3.4+ ssl context creation is
# supported. Protocol_TLS from 2.7.13 and from 3.5.3
# replaced SSLv23. Functionality is similar.
if hasattr(ssl, 'PROTOCOL_TLS'):
p = 'PROTOCOL_TLS'
else:
p = 'PROTOCOL_SSLv23'
ssl_args = {'ssl_ctx': ssl.SSLContext(getattr(ssl, p))}
# Restrict non-safe versions
ssl_args['ssl_ctx'].options |= ssl.OP_NO_SSLv3 | ssl.OP_NO_SSLv2
if CONF.ciphers is not None:
ssl_args['ciphers'] = CONF.ciphers
if CONF.ca_certs is not None:
server = StreamServer((CONF.ofp_listen_host,
ofp_ssl_listen_port),
@ -170,15 +193,13 @@ class OpenFlowController(object):
keyfile=CONF.ctl_privkey,
certfile=CONF.ctl_cert,
cert_reqs=ssl.CERT_REQUIRED,
ca_certs=CONF.ca_certs,
ssl_version=ssl.PROTOCOL_TLSv1)
ca_certs=CONF.ca_certs, **ssl_args)
else:
server = StreamServer((CONF.ofp_listen_host,
ofp_ssl_listen_port),
datapath_connection_factory,
keyfile=CONF.ctl_privkey,
certfile=CONF.ctl_cert,
ssl_version=ssl.PROTOCOL_TLSv1)
certfile=CONF.ctl_cert, **ssl_args)
else:
server = StreamServer((CONF.ofp_listen_host,
ofp_tcp_listen_port),
@ -194,12 +215,10 @@ def _deactivate(method):
method(self)
finally:
try:
self.socket.shutdown(SHUT_RDWR)
except (EOFError, IOError):
self.socket.close()
except IOError:
pass
if not self.is_active:
self.socket.close()
return deactivate
@ -277,14 +296,24 @@ class Datapath(ofproto_protocol.ProtocolDesc):
self._ports = None
self.flow_format = ofproto_v1_0.NXFF_OPENFLOW10
self.ofp_brick = ryu.base.app_manager.lookup_service_brick('ofp_event')
self.state = None # for pylint
self.set_state(HANDSHAKE_DISPATCHER)
@_deactivate
def _close_write(self):
# Note: Close only further sends in order to wait for the switch to
# disconnect this connection.
try:
self.socket.shutdown(SHUT_WR)
except (EOFError, IOError):
pass
def close(self):
if self.state != DEAD_DISPATCHER:
self.set_state(DEAD_DISPATCHER)
self.set_state(DEAD_DISPATCHER)
self._close_write()
def set_state(self, state):
if self.state == state:
return
self.state = state
ev = ofp_event.EventOFPStateChange(self)
ev.state = state
@ -300,7 +329,7 @@ class Datapath(ofproto_protocol.ProtocolDesc):
while self.state != DEAD_DISPATCHER:
try:
read_len = min_read_len
if (remaining_read_len > min_read_len):
if remaining_read_len > min_read_len:
read_len = remaining_read_len
ret = self.socket.recv(read_len)
except SocketTimeout:
@ -312,14 +341,14 @@ class Datapath(ofproto_protocol.ProtocolDesc):
except (EOFError, IOError):
break
if len(ret) == 0:
if not ret:
break
buf += ret
buf_len = len(buf)
while buf_len >= min_read_len:
(version, msg_type, msg_len, xid) = ofproto_parser.header(buf)
if (msg_len < min_read_len):
if msg_len < min_read_len:
# Someone isn't playing nicely; log it, and try something sane.
LOG.debug("Message with invalid length %s received from switch at address %s",
msg_len, self.address)
@ -335,7 +364,9 @@ class Datapath(ofproto_protocol.ProtocolDesc):
ev = ofp_event.ofp_msg_to_ev(msg)
self.ofp_brick.send_event_to_observers(ev, self.state)
dispatchers = lambda x: x.callers[ev.__class__].dispatchers
def dispatchers(x):
return x.callers[ev.__class__].dispatchers
handlers = [handler for handler in
self.ofp_brick.get_handlers(ev) if
self.state in dispatchers(handler)]
@ -358,9 +389,11 @@ class Datapath(ofproto_protocol.ProtocolDesc):
def _send_loop(self):
try:
while self.state != DEAD_DISPATCHER:
buf = self.send_q.get()
buf, close_socket = self.send_q.get()
self._send_q_sem.release()
self.socket.sendall(buf)
if close_socket:
break
except SocketTimeout:
LOG.debug("Socket timed out while sending data to switch at address %s",
self.address)
@ -380,14 +413,14 @@ class Datapath(ofproto_protocol.ProtocolDesc):
self._send_q_sem.release()
except hub.QueueEmpty:
pass
# Finally, ensure the _recv_loop terminates.
self.close()
# Finally, disallow further sends.
self._close_write()
def send(self, buf):
def send(self, buf, close_socket=False):
msg_enqueued = False
self._send_q_sem.acquire()
if self.send_q:
self.send_q.put(buf)
self.send_q.put((buf, close_socket))
msg_enqueued = True
else:
self._send_q_sem.release()
@ -402,13 +435,13 @@ class Datapath(ofproto_protocol.ProtocolDesc):
msg.set_xid(self.xid)
return self.xid
def send_msg(self, msg):
def send_msg(self, msg, close_socket=False):
assert isinstance(msg, self.ofproto_parser.MsgBase)
if msg.xid is None:
self.set_xid(msg)
msg.serialize()
# LOG.debug('send_msg %s', msg)
return self.send(msg.buf)
return self.send(msg.buf, close_socket=close_socket)
def _echo_request_loop(self):
if not self.max_unreplied_echo_requests:
@ -424,7 +457,7 @@ class Datapath(ofproto_protocol.ProtocolDesc):
def acknowledge_echo_reply(self, xid):
try:
self.unreplied_echo_requests.remove(xid)
except:
except ValueError:
pass
def serve(self):

View File

@ -165,10 +165,33 @@ class DPSet(app_manager.RyuApp):
"""
DPSet application manages a set of switches (datapaths)
connected to this controller.
Usage Example::
# ...(snip)...
from ryu.controller import dpset
class MyApp(app_manager.RyuApp):
_CONTEXTS = {
'dpset': dpset.DPSet,
}
def __init__(self, *args, **kwargs):
super(MyApp, self).__init__(*args, **kwargs)
# Stores DPSet instance to call its API in this app
self.dpset = kwargs['dpset']
def _my_handler(self):
# Get the datapath object which has the given dpid
dpid = 1
dp = self.dpset.get(dpid)
if dp is None:
self.logger.info('No such datapath: dpid=%d', dpid)
"""
def __init__(self, *args, **kwargs):
super(DPSet, self).__init__()
super(DPSet, self).__init__(*args, **kwargs)
self.name = 'dpset'
self.dps = {} # datapath_id => class Datapath
@ -238,9 +261,10 @@ class DPSet(app_manager.RyuApp):
"""
This method returns a list of tuples which represents
instances for switches connected to this controller.
The tuple consists of a Datapath Id and an instance of
The tuple consists of a Datapath ID and an instance of
ryu.controller.controller.Datapath.
A return value looks like the following:
A return value looks like the following::
[ (dpid_A, Datapath_A), (dpid_B, Datapath_B), ... ]
"""

View File

@ -60,12 +60,13 @@ class OFPHandler(ryu.base.app_manager.RyuApp):
return hub.spawn(self.controller)
def _hello_failed(self, datapath, error_desc):
self.logger.error(error_desc)
error_msg = datapath.ofproto_parser.OFPErrorMsg(datapath)
error_msg.type = datapath.ofproto.OFPET_HELLO_FAILED
error_msg.code = datapath.ofproto.OFPHFC_INCOMPATIBLE
error_msg.data = error_desc
datapath.send_msg(error_msg)
self.logger.error('%s on datapath %s', error_desc, datapath.address)
error_msg = datapath.ofproto_parser.OFPErrorMsg(
datapath=datapath,
type_=datapath.ofproto.OFPET_HELLO_FAILED,
code=datapath.ofproto.OFPHFC_INCOMPATIBLE,
data=error_desc)
datapath.send_msg(error_msg, close_socket=True)
@set_ev_handler(ofp_event.EventOFPHello, HANDSHAKE_DISPATCHER)
def hello_handler(self, ev):

View File

@ -42,6 +42,7 @@ if HUB_TYPE == 'eventlet':
import ssl
import socket
import traceback
import sys
getcurrent = eventlet.getcurrent
patch = eventlet.monkey_patch
@ -126,11 +127,25 @@ if HUB_TYPE == 'eventlet':
self.server = eventlet.listen(listen_info)
if ssl_args:
def wrap_and_handle(sock, addr):
ssl_args.setdefault('server_side', True)
handle(ssl.wrap_socket(sock, **ssl_args), addr)
ssl_args.setdefault('server_side', True)
if 'ssl_ctx' in ssl_args:
ctx = ssl_args.pop('ssl_ctx')
ctx.load_cert_chain(ssl_args.pop('certfile'),
ssl_args.pop('keyfile'))
if 'cert_reqs' in ssl_args:
ctx.verify_mode = ssl_args.pop('cert_reqs')
if 'ca_certs' in ssl_args:
ctx.load_verify_locations(ssl_args.pop('ca_certs'))
self.handle = wrap_and_handle
def wrap_and_handle_ctx(sock, addr):
handle(ctx.wrap_socket(sock, **ssl_args), addr)
self.handle = wrap_and_handle_ctx
else:
def wrap_and_handle_ssl(sock, addr):
handle(ssl.wrap_socket(sock, **ssl_args), addr)
self.handle = wrap_and_handle_ssl
else:
self.handle = handle

View File

@ -84,7 +84,7 @@ def ipv4_to_str(ip):
:param ip: binary or int type representation of IPv4 address
:return: IPv4 address string
"""
if isinstance(ip, int):
if isinstance(ip, numbers.Integral):
return addrconv.ipv4.bin_to_text(struct.pack("!I", ip))
else:
return addrconv.ipv4.bin_to_text(ip)

View File

@ -264,6 +264,12 @@ class Ospf2MrtMessage(MrtMessage):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
_HEADER_FMT = '!4s4s'
HEADER_SIZE = struct.calcsize(_HEADER_FMT)
_TYPE = {
'ascii': [
'remote_ip',
'local_ip',
],
}
def __init__(self, remote_ip, local_ip, ospf_message):
self.remote_ip = remote_ip
@ -328,6 +334,12 @@ class TableDumpMrtMessage(MrtMessage):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
_HEADER_FMT = '' # should be defined in subclass
HEADER_SIZE = 0
_TYPE = {
'ascii': [
'prefix',
'peer_ip',
],
}
def __init__(self, view_num, seq_num, prefix, prefix_len, status,
originated_time, peer_ip, peer_as, bgp_attributes,
@ -431,6 +443,11 @@ class TableDump2MrtRecord(MrtCommonRecord):
SUBTYPE_RIB_IPV6_UNICAST = 4
SUBTYPE_RIB_IPV6_MULTICAST = 5
SUBTYPE_RIB_GENERIC = 6
SUBTYPE_RIB_IPV4_UNICAST_ADDPATH = 8
SUBTYPE_RIB_IPV4_MULTICAST_ADDPATH = 9
SUBTYPE_RIB_IPV6_UNICAST_ADDPATH = 10
SUBTYPE_RIB_IPV6_MULTICAST_ADDPATH = 11
SUBTYPE_RIB_GENERIC_ADDPATH = 12
@TableDump2MrtMessage.register_type(
@ -452,6 +469,11 @@ class TableDump2PeerIndexTableMrtMessage(TableDump2MrtMessage):
HEADER_SIZE = struct.calcsize(_HEADER_FMT)
_PEER_COUNT_FMT = '!H'
PEER_COUNT_SIZE = struct.calcsize(_PEER_COUNT_FMT)
_TYPE = {
'ascii': [
'bgp_id',
],
}
def __init__(self, bgp_id, peer_entries,
view_name='', view_name_len=None, peer_count=None):
@ -535,6 +557,13 @@ class MrtPeer(stringify.StringifyMixin):
IP_ADDR_FAMILY_BIT = 1 << 0
AS_NUMBER_SIZE_BIT = 1 << 1
_TYPE = {
'ascii': [
'bgp_id',
'ip_addr',
],
}
def __init__(self, bgp_id, ip_addr, as_num, type_=0):
self.type = type_
self.bgp_id = bgp_id
@ -595,7 +624,8 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage):
RIB subtypes.
The AFI/SAFI-specific RIB subtypes consist of the RIB_IPV4_UNICAST,
RIB_IPV4_MULTICAST, RIB_IPV6_UNICAST, and RIB_IPV6_MULTICAST subtypes.
RIB_IPV4_MULTICAST, RIB_IPV6_UNICAST, RIB_IPV6_MULTICAST and their
additional-path version subtypes.
"""
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -614,6 +644,9 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage):
# Parser class to parse the Prefix field
_PREFIX_CLS = None # should be defined in subclass
# Is additional-path version?
_IS_ADDPATH = False
def __init__(self, seq_num, prefix, rib_entries, entry_count=None):
self.seq_num = seq_num
assert isinstance(prefix, self._PREFIX_CLS)
@ -631,7 +664,7 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage):
rest = buf[2:]
rib_entries = []
for i in range(entry_count):
r, rest = MrtRibEntry.parse(rest)
r, rest = MrtRibEntry.parse(rest, is_addpath=cls._IS_ADDPATH)
rib_entries.insert(i, r)
return entry_count, rib_entries, rest
@ -667,31 +700,104 @@ class TableDump2AfiSafiSpecificRibMrtMessage(TableDump2MrtMessage):
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV4_UNICAST)
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV4_MULTICAST)
class TableDump2RibIPv4UnicastMrtMessage(TableDump2AfiSafiSpecificRibMrtMessage):
class TableDump2RibIPv4UnicastMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
RIB_IPV4_UNICAST/SUBTYPE_RIB_IPV4_MULTICAST subtype.
SUBTYPE_RIB_IPV4_UNICAST subtype.
"""
_PREFIX_CLS = bgp.IPAddrPrefix
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV4_MULTICAST)
class TableDump2RibIPv4MulticastMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
SUBTYPE_RIB_IPV4_MULTICAST subtype.
"""
_PREFIX_CLS = bgp.IPAddrPrefix
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV6_UNICAST)
class TableDump2RibIPv6UnicastMrtMessage(TableDump2AfiSafiSpecificRibMrtMessage):
class TableDump2RibIPv6UnicastMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
RIB_IPV6_UNICAST/SUBTYPE_RIB_IPV6_MULTICAST subtype.
SUBTYPE_RIB_IPV6_MULTICAST subtype.
"""
_PREFIX_CLS = bgp.IP6AddrPrefix
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV6_MULTICAST)
class TableDump2RibIPv6MulticastMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
SUBTYPE_RIB_IPV6_MULTICAST subtype.
"""
_PREFIX_CLS = bgp.IP6AddrPrefix
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV4_UNICAST_ADDPATH)
class TableDump2RibIPv4UnicastAddPathMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
SUBTYPE_RIB_IPV4_UNICAST_ADDPATH subtype.
"""
_PREFIX_CLS = bgp.IPAddrPrefix
_IS_ADDPATH = True
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV4_MULTICAST_ADDPATH)
class TableDump2RibIPv4MulticastAddPathMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
SUBTYPE_RIB_IPV4_MULTICAST_ADDPATH subtype.
"""
_PREFIX_CLS = bgp.IPAddrPrefix
_IS_ADDPATH = True
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV6_UNICAST_ADDPATH)
class TableDump2RibIPv6UnicastAddPathMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
SUBTYPE_RIB_IPV6_UNICAST_ADDPATH subtype.
"""
_PREFIX_CLS = bgp.IP6AddrPrefix
_IS_ADDPATH = True
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_IPV6_MULTICAST_ADDPATH)
class TableDump2RibIPv6MulticastAddPathMrtMessage(
TableDump2AfiSafiSpecificRibMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the
SUBTYPE_RIB_IPV6_MULTICAST_ADDPATH subtype.
"""
_PREFIX_CLS = bgp.IP6AddrPrefix
_IS_ADDPATH = True
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_GENERIC)
class TableDump2RibGenericMrtMessage(TableDump2MrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the RIB_GENERIC subtype.
MRT Message for the TABLE_DUMP_V2 Type and the generic RIB subtypes.
The generic RIB subtypes consist of the RIB_GENERIC and
RIB_GENERIC_ADDPATH subtypes.
"""
# 0 1 2 3
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@ -707,6 +813,9 @@ class TableDump2RibGenericMrtMessage(TableDump2MrtMessage):
_HEADER_FMT = '!IHB'
HEADER_SIZE = struct.calcsize(_HEADER_FMT)
# Is additional-path version?
_IS_ADDPATH = False
def __init__(self, seq_num, afi, safi, nlri, rib_entries,
entry_count=None):
self.seq_num = seq_num
@ -727,7 +836,7 @@ class TableDump2RibGenericMrtMessage(TableDump2MrtMessage):
rest = buf[2:]
rib_entries = []
for i in range(entry_count):
r, rest = MrtRibEntry.parse(rest)
r, rest = MrtRibEntry.parse(rest, is_addpath=cls._IS_ADDPATH)
rib_entries.insert(i, r)
return entry_count, rib_entries, rest
@ -762,6 +871,16 @@ class TableDump2RibGenericMrtMessage(TableDump2MrtMessage):
self.afi, self.safi) + nlri_bin + rib_bin
@TableDump2MrtMessage.register_type(
TableDump2MrtRecord.SUBTYPE_RIB_GENERIC_ADDPATH)
class TableDump2RibGenericAddPathMrtMessage(TableDump2RibGenericMrtMessage):
"""
MRT Message for the TABLE_DUMP_V2 Type and the RIB_GENERIC_ADDPATH
subtype.
"""
_IS_ADDPATH = True
class MrtRibEntry(stringify.StringifyMixin):
"""
MRT RIB Entry.
@ -773,15 +892,21 @@ class MrtRibEntry(stringify.StringifyMixin):
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Originated Time |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | (Path Identifier) |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | Attribute Length |
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | BGP Attributes... (variable)
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# peer_index, originated_time, attr_len
_HEADER_FMT = '!HIH'
HEADER_SIZE = struct.calcsize(_HEADER_FMT)
# peer_index, originated_time, path_id, attr_len
_HEADER_FMT_ADDPATH = '!HIIH'
HEADER_SIZE_ADDPATH = struct.calcsize(_HEADER_FMT_ADDPATH)
def __init__(self, peer_index, originated_time, bgp_attributes,
attr_len=None):
attr_len=None, path_id=None):
self.peer_index = peer_index
self.originated_time = originated_time
assert isinstance(bgp_attributes, (list, tuple))
@ -789,20 +914,28 @@ class MrtRibEntry(stringify.StringifyMixin):
assert isinstance(attr, bgp._PathAttribute)
self.bgp_attributes = bgp_attributes
self.attr_len = attr_len
self.path_id = path_id
@classmethod
def parse(cls, buf):
(peer_index, originated_time, attr_len) = struct.unpack_from(
cls._HEADER_FMT, buf)
def parse(cls, buf, is_addpath=False):
path_id = None
if not is_addpath:
(peer_index, originated_time,
attr_len) = struct.unpack_from(cls._HEADER_FMT, buf)
_header_size = cls.HEADER_SIZE
else:
(peer_index, originated_time, path_id,
attr_len) = struct.unpack_from(cls._HEADER_FMT_ADDPATH, buf)
_header_size = cls.HEADER_SIZE_ADDPATH
bgp_attr_bin = buf[cls.HEADER_SIZE:cls.HEADER_SIZE + attr_len]
bgp_attr_bin = buf[_header_size:_header_size + attr_len]
bgp_attributes = []
while bgp_attr_bin:
attr, bgp_attr_bin = bgp._PathAttribute.parser(bgp_attr_bin)
bgp_attributes.append(attr)
return cls(peer_index, originated_time, bgp_attributes,
attr_len), buf[cls.HEADER_SIZE + attr_len:]
attr_len, path_id), buf[_header_size + attr_len:]
def serialize(self):
bgp_attrs_bin = bytearray()
@ -810,10 +943,17 @@ class MrtRibEntry(stringify.StringifyMixin):
bgp_attrs_bin += attr.serialize()
self.attr_len = len(bgp_attrs_bin) # fixup
return struct.pack(self._HEADER_FMT,
self.peer_index,
self.originated_time,
self.attr_len) + bgp_attrs_bin
if self.path_id is None:
return struct.pack(self._HEADER_FMT,
self.peer_index,
self.originated_time,
self.attr_len) + bgp_attrs_bin
else:
return struct.pack(self._HEADER_FMT_ADDPATH,
self.peer_index,
self.originated_time,
self.path_id,
self.attr_len) + bgp_attrs_bin
@six.add_metaclass(abc.ABCMeta)
@ -821,6 +961,12 @@ class Bgp4MpMrtMessage(MrtMessage):
"""
MRT Message for the BGP4MP Type.
"""
_TYPE = {
'ascii': [
'peer_ip',
'local_ip',
],
}
@MrtRecord.register_type(MrtRecord.TYPE_BGP4MP)
@ -834,6 +980,10 @@ class Bgp4MpMrtRecord(MrtCommonRecord):
SUBTYPE_BGP4MP_STATE_CHANGE_AS4 = 5
SUBTYPE_BGP4MP_MESSAGE_LOCAL = 6
SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL = 7
SUBTYPE_BGP4MP_MESSAGE_ADDPATH = 8
SUBTYPE_BGP4MP_MESSAGE_AS4_ADDPATH = 9
SUBTYPE_BGP4MP_MESSAGE_LOCAL_ADDPATH = 10
SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH = 11
@MrtRecord.register_type(MrtRecord.TYPE_BGP4MP_ET)
@ -847,6 +997,10 @@ class Bgp4MpEtMrtRecord(ExtendedTimestampMrtRecord):
SUBTYPE_BGP4MP_STATE_CHANGE_AS4 = 5
SUBTYPE_BGP4MP_MESSAGE_LOCAL = 6
SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL = 7
SUBTYPE_BGP4MP_MESSAGE_ADDPATH = 8
SUBTYPE_BGP4MP_MESSAGE_AS4_ADDPATH = 9
SUBTYPE_BGP4MP_MESSAGE_LOCAL_ADDPATH = 10
SUBTYPE_BGP4MP_MESSAGE_AS4_LOCAL_ADDPATH = 11
@Bgp4MpMrtMessage.register_type(

View File

@ -39,7 +39,7 @@ def ofp_instruction_from_str(ofproto, action_str):
action_str An action string.
=========== =================================================
"""
action_re = re.compile("([a-z_]+)(\([^)]*\)|[^a-z_,()][^,()]*)*")
action_re = re.compile(r"([a-z_]+)(\([^)]*\)|[^a-z_,()][^,()]*)*")
result = []
while len(action_str):
m = action_re.match(action_str)
@ -303,7 +303,7 @@ class OfctlActionConverter(object):
if k == 'table':
recirc_table = str_to_int(v)
elif k == 'zone':
m = re.search('\[(\d*)\.\.(\d*)\]', v)
m = re.search(r'\[(\d*)\.\.(\d*)\]', v)
if m:
zone_ofs_nbits = nicira_ext.ofs_nbits(
int(m.group(1)), int(m.group(2)))
@ -322,3 +322,7 @@ class OfctlActionConverter(object):
'recirc_table': recirc_table,
'alg': alg,
'actions': ct_actions})
@classmethod
def ct_clear(cls, ofproto, action_str):
return dict(NXActionCTClear={})

View File

@ -15,7 +15,7 @@
# limitations under the License.
"""
slimmed down version of OVSBridge in quantum agent
Wrapper utility library of :py:mod:`ryu.lib.ovs.vsctl`
"""
import functools
@ -92,6 +92,26 @@ class TunnelPort(object):
class OVSBridge(object):
"""
Class to provide wrapper utilities of :py:mod:`ryu.lib.ovs.vsctl.VSCtl`
``CONF`` is a instance of ``oslo_config.cfg.ConfigOpts``.
Mostly ``self.CONF`` is sufficient to instantiate this class from your Ryu
application.
``datapath_id`` specifies Datapath ID of the target OVS instance.
``ovsdb_addr`` specifies the address of the OVS instance.
Automatically validated when you call ``init()`` method.
Refer to :py:mod:`ryu.lib.ovs.vsctl.valid_ovsdb_addr` for the format of
this address.
if ``timeout`` is omitted, ``CONF.ovsdb_timeout`` will be used as the
default value.
Usage of ``timeout`` and ``exception`` is the same with ``timeout_sec``
and ``exception`` of :py:mod:`ryu.lib.ovs.vsctl.VSCtl.run_command`.
"""
def __init__(self, CONF, datapath_id, ovsdb_addr, timeout=None,
exception=None):
@ -105,9 +125,25 @@ class OVSBridge(object):
self.br_name = None
def run_command(self, commands):
"""
Executes the given commands and sends OVSDB messages.
``commands`` must be a list of
:py:mod:`ryu.lib.ovs.vsctl.VSCtlCommand`.
The given ``timeout`` and ``exception`` when instantiation will be used
to call :py:mod:`ryu.lib.ovs.vsctl.VSCtl.run_command`.
"""
self.vsctl.run_command(commands, self.timeout, self.exception)
def init(self):
"""
Validates the given ``ovsdb_addr`` and connects to OVS instance.
If failed to connect to OVS instance or the given ``datapath_id`` does
not match with the Datapath ID of the connected OVS instance, raises
:py:mod:`ryu.lib.ovs.bridge.OVSBridgeNotFound` exception.
"""
if not valid_ovsdb_addr(self.ovsdb_addr):
raise ValueError('Invalid OVSDB address: %s' % self.ovsdb_addr)
if self.br_name is None:
@ -126,16 +162,38 @@ class OVSBridge(object):
return command.result[0].name
def get_controller(self):
"""
Gets the configured OpenFlow controller address.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl get-controller <bridge>
"""
command = ovs_vsctl.VSCtlCommand('get-controller', [self.br_name])
self.run_command([command])
return command.result[0]
result = command.result
return result[0] if len(result) == 1 else result
def set_controller(self, controllers):
"""
Sets the OpenFlow controller address.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl set-controller <bridge> <target>...
"""
command = ovs_vsctl.VSCtlCommand('set-controller', [self.br_name])
command.args.extend(controllers)
self.run_command([command])
def del_controller(self):
"""
Deletes the configured OpenFlow controller address.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl del-controller <bridge>
"""
command = ovs_vsctl.VSCtlCommand('del-controller', [self.br_name])
self.run_command([command])
@ -245,30 +303,72 @@ class OVSBridge(object):
self.run_command([command])
def db_get_val(self, table, record, column):
"""
Gets values of 'column' in 'record' in 'table'.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl get TBL REC COL
"""
command = ovs_vsctl.VSCtlCommand('get', (table, record, column))
self.run_command([command])
assert len(command.result) == 1
return command.result[0]
def db_get_map(self, table, record, column):
"""
Gets dict type value of 'column' in 'record' in 'table'.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl get TBL REC COL
"""
val = self.db_get_val(table, record, column)
assert isinstance(val, dict)
return val
def get_datapath_id(self):
"""
Gets Datapath ID of OVS instance.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl get Bridge <bridge> datapath_id
"""
return self.db_get_val('Bridge', self.br_name, 'datapath_id')
def delete_port(self, port_name):
"""
Deletes a port on the OVS instance.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl --if-exists del-port <bridge> <port>
"""
command = ovs_vsctl.VSCtlCommand(
'del-port', (self.br_name, port_name), '--if-exists')
self.run_command([command])
def get_ofport(self, port_name):
"""
Gets the OpenFlow port number.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl get Interface <port> ofport
"""
ofport_list = self.db_get_val('Interface', port_name, 'ofport')
assert len(ofport_list) == 1
return int(ofport_list[0])
def get_port_name_list(self):
"""
Gets a list of all ports on OVS instance.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl list-ports <bridge>
"""
command = ovs_vsctl.VSCtlCommand('list-ports', (self.br_name, ))
self.run_command([command])
return command.result
@ -297,6 +397,16 @@ class OVSBridge(object):
def add_tunnel_port(self, name, tunnel_type, remote_ip,
local_ip=None, key=None, ofport=None):
"""
Creates a tunnel port.
:param name: Port name to be created
:param tunnel_type: Type of tunnel (gre or vxlan)
:param remote_ip: Remote IP address of tunnel
:param local_ip: Local IP address of tunnel
:param key: Key of GRE or VNI of VxLAN
:param ofport: Requested OpenFlow port number
"""
options = 'remote_ip=%(remote_ip)s' % locals()
if key:
options += ',key=%(key)s' % locals()
@ -314,15 +424,32 @@ class OVSBridge(object):
def add_gre_port(self, name, remote_ip,
local_ip=None, key=None, ofport=None):
"""
Creates a GRE tunnel port.
See the description of ``add_tunnel_port()``.
"""
self.add_tunnel_port(name, 'gre', remote_ip,
local_ip=local_ip, key=key, ofport=ofport)
def add_vxlan_port(self, name, remote_ip,
local_ip=None, key=None, ofport=None):
"""
Creates a VxLAN tunnel port.
See the description of ``add_tunnel_port()``.
"""
self.add_tunnel_port(name, 'vxlan', remote_ip,
local_ip=local_ip, key=key, ofport=ofport)
def del_port(self, port_name):
"""
Deletes a port on OVS instance.
This method is corresponding to the following ovs-vsctl command::
$ ovs-vsctl del-port <bridge> <port>
"""
command = ovs_vsctl.VSCtlCommand('del-port', (self.br_name, port_name))
self.run_command([command])
@ -396,6 +523,9 @@ class OVSBridge(object):
return None
def set_qos(self, port_name, type='linux-htb', max_rate=None, queues=None):
"""
Sets a Qos rule and creates Queues on the given port.
"""
queues = queues if queues else []
command_qos = ovs_vsctl.VSCtlCommand(
'set-qos',
@ -409,6 +539,9 @@ class OVSBridge(object):
return None
def del_qos(self, port_name):
"""
Deletes the Qos rule on the given port.
"""
command = ovs_vsctl.VSCtlCommand(
'del-qos',
[port_name])

View File

@ -14,6 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""
``ovs-vsctl`` command like library to speak OVSDB protocol
"""
from __future__ import print_function
@ -53,9 +56,9 @@ def valid_ovsdb_addr(addr):
The valid formats are:
- unix:file
- tcp:ip:port
- ssl:ip:port
- ``unix:file``
- ``tcp:ip:port``
- ``ssl:ip:port``
If ip is IPv6 address, wrap ip with brackets (e.g., ssl:[::1]:6640).
@ -63,12 +66,12 @@ def valid_ovsdb_addr(addr):
:return: True if valid, otherwise False.
"""
# Assumes Unix socket format: "unix:file"
m = re.match('unix:(\S+)', addr)
m = re.match(r'unix:(\S+)', addr)
if m:
file = m.group(1)
return os.path.isfile(file)
# Assumes TCP/SSL socket format: "tcp:ip:port" or "ssl:ip:port"
m = re.match('(tcp|ssl):(\S+):(\d+)', addr)
m = re.match(r'(tcp|ssl):(\S+):(\d+)', addr)
if m:
address = m.group(2)
port = m.group(3)
@ -959,6 +962,34 @@ class _VSCtlTable(object):
class VSCtlCommand(StringifyMixin):
"""
Class to describe artgumens similar to those of ``ovs-vsctl`` command.
``command`` specifies the command of ``ovs-vsctl``.
``args`` specifies a list or tuple of arguments for the given command.
``options`` specifies a list or tuple of options for the given command.
Please note that NOT all options of ``ovs-vsctl`` are supported.
For example, ``--id`` option is not yet supported.
This class supports the followings.
================= =========================================================
Option Description
================= =========================================================
``--may-exist`` Does nothing when the given port already exists.
The supported commands are ``add-port`` and
``add-bond``.
``--fake-iface`` Creates a port as a fake interface.
The supported command is ``add-bond``.
``--must-exist`` Raises exception if the given port does not exist.
The supported command is ``del-port``.
``--with-iface`` Takes effect to the interface which has the same name.
The supported command is ``del-port``.
``--if-exists`` Ignores exception when not found.
The supported command is ``get``.
================= =========================================================
"""
def __init__(self, command, args=None, options=None):
super(VSCtlCommand, self).__init__()
@ -978,6 +1009,13 @@ class VSCtlCommand(StringifyMixin):
class VSCtl(object):
"""
A class to describe an Open vSwitch instance.
``remote`` specifies the address of the OVS instance.
:py:mod:`ryu.lib.ovs.vsctl.valid_ovsdb_addr` is a convenient function to
validate this address.
"""
def _reset(self):
self.schema_helper = None
@ -1237,6 +1275,19 @@ class VSCtl(object):
self._do_main(commands)
def run_command(self, commands, timeout_sec=None, exception=None):
"""
Executes the given commands and sends OVSDB messages.
``commands`` must be a list of
:py:mod:`ryu.lib.ovs.vsctl.VSCtlCommand`.
If ``timeout_sec`` is specified, raises exception after the given
timeout [sec]. Additionally, if ``exception`` is specified, this
function will wraps exception using the given exception class.
Retruns ``None`` but fills ``result`` attribute for each command
instance.
"""
if timeout_sec is None:
self._run_command(commands)
else:
@ -1563,7 +1614,9 @@ class VSCtl(object):
self._pre_add_port(ctx, columns)
def _cmd_add_port(self, ctx, command):
may_exist = command.has_option('--may_exist')
# '--may_exist' is a typo but for backword compatibility
may_exist = (command.has_option('--may_exist')
or command.has_option('--may-exist'))
br_name = command.args[0]
port_name = command.args[1]
@ -1577,7 +1630,9 @@ class VSCtl(object):
False, iface_names, settings)
def _cmd_add_bond(self, ctx, command):
may_exist = command.has_option('--may_exist')
# '--may_exist' is a typo but for backword compatibility
may_exist = (command.has_option('--may_exist')
or command.has_option('--may-exist'))
fake_iface = command.has_option('--fake-iface')
br_name = command.args[0]

View File

@ -782,7 +782,16 @@ class _LabelledAddrPrefix(_AddrPrefix):
# Routes field should be set to 0x800000. (Of course, terminating the
# BGP session also withdraws all the previously advertised routes.)
#
_WITHDRAW_LABEL = 0x800000
# RFC8227
# 2.4 How to Explicitly Withdraw the Binding of a Label to a Prefix
# [RFC3107] also made it possible to withdraw a binding without specifying
# the label explicitly, by setting the Compatibility field to 0x800000.
# However, some implementations set it to 0x000000. In order to ensure
# backwards compatibility, it is RECOMMENDED by this document that the
# Compatibility field be set to 0x800000, but it is REQUIRED that it be
# ignored upon reception.
#
_WITHDRAW_LABELS = [0x800000, 0x000000]
def __init__(self, length, addr, labels=None, **kwargs):
labels = labels if labels else []
@ -823,7 +832,7 @@ class _LabelledAddrPrefix(_AddrPrefix):
labels = addr[0]
rest = addr[1:]
labels = [x << 4 for x in labels]
if labels and labels[-1] != cls._WITHDRAW_LABEL:
if labels and labels[-1] not in cls._WITHDRAW_LABELS:
labels[-1] |= 1 # bottom of stack
bin_labels = list(cls._label_to_bin(l) for l in labels)
return bytes(reduce(lambda x, y: x + y, bin_labels,
@ -837,7 +846,7 @@ class _LabelledAddrPrefix(_AddrPrefix):
while True:
(label, bin_) = cls._label_from_bin(bin_)
labels.append(label)
if label & 1 or label == cls._WITHDRAW_LABEL:
if label & 1 or label in cls._WITHDRAW_LABELS:
break
assert length > struct.calcsize(cls._LABEL_PACK_STR) * len(labels)
except struct.error:
@ -857,7 +866,7 @@ class _LabelledAddrPrefix(_AddrPrefix):
while True:
(label, rest) = cls._label_from_bin(rest)
labels.append(label >> 4)
if label & 1 or label == cls._WITHDRAW_LABEL:
if label & 1 or label in cls._WITHDRAW_LABELS:
break
return (labels,) + cls._prefix_from_bin(rest)

View File

@ -60,6 +60,8 @@ BMP_STAT_TYPE_INV_UPDATE_DUE_TO_ORIGINATOR_ID = 5
BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP = 6
BMP_STAT_TYPE_ADJ_RIB_IN = 7
BMP_STAT_TYPE_LOC_RIB = 8
BMP_STAT_TYPE_ADJ_RIB_OUT = 14
BMP_STAT_TYPE_EXPORT_RIB = 15
BMP_PEER_DOWN_REASON_UNKNOWN = 0
BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION = 1
@ -69,7 +71,7 @@ BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION = 4
class BMPMessage(packet_base.PacketBase, TypeDisp):
"""Base class for BGP Monitoring Protocol messages.
r"""Base class for BGP Monitoring Protocol messages.
An instance has the following attributes at least.
Most of them are same to the on-wire counterparts but in host byte
@ -141,7 +143,7 @@ class BMPMessage(packet_base.PacketBase, TypeDisp):
class BMPPeerMessage(BMPMessage):
"""BMP Message with Per Peer Header
r"""BMP Message with Per Peer Header
Following BMP Messages contain Per Peer Header after Common BMP Header.
@ -157,7 +159,8 @@ class BMPPeerMessage(BMPMessage):
type Type field. one of BMP\_MSG\_ constants.
peer_type The type of the peer.
is_post_policy Indicate the message reflects the post-policy
Adj-RIB-In
is_adj_rib_out Indicate the message reflects Adj-RIB-Out (defaults
to Adj-RIB-In)
peer_distinguisher Use for L3VPN router which can have multiple
instance.
peer_address The remote IP address associated with the TCP
@ -179,12 +182,13 @@ class BMPPeerMessage(BMPMessage):
def __init__(self, peer_type, is_post_policy, peer_distinguisher,
peer_address, peer_as, peer_bgp_id, timestamp,
version=VERSION, type_=None, len_=None):
version=VERSION, type_=None, len_=None, is_adj_rib_out=False):
super(BMPPeerMessage, self).__init__(version=version,
len_=len_,
type_=type_)
self.peer_type = peer_type
self.is_post_policy = is_post_policy
self.is_adj_rib_out = is_adj_rib_out
self.peer_distinguisher = peer_distinguisher
self.peer_address = peer_address
self.peer_as = peer_as
@ -200,6 +204,11 @@ class BMPPeerMessage(BMPMessage):
rest = buf[struct.calcsize(cls._PEER_HDR_PACK_STR):]
if peer_flags & (1 << 4):
is_adj_rib_out = True
else:
is_adj_rib_out = False
if peer_flags & (1 << 6):
is_post_policy = True
else:
@ -221,12 +230,16 @@ class BMPPeerMessage(BMPMessage):
"peer_address": peer_address,
"peer_as": peer_as,
"peer_bgp_id": peer_bgp_id,
"timestamp": timestamp
"timestamp": timestamp,
"is_adj_rib_out": is_adj_rib_out,
}, rest
def serialize_tail(self):
flags = 0
if self.is_adj_rib_out:
flags |= (1 << 4)
if self.is_post_policy:
flags |= (1 << 6)
@ -250,7 +263,7 @@ class BMPPeerMessage(BMPMessage):
@BMPMessage.register_type(BMP_MSG_ROUTE_MONITORING)
class BMPRouteMonitoring(BMPPeerMessage):
"""BMP Route Monitoring Message
r"""BMP Route Monitoring Message
========================== ===============================================
Attribute Description
@ -275,7 +288,7 @@ class BMPRouteMonitoring(BMPPeerMessage):
def __init__(self, bgp_update, peer_type, is_post_policy,
peer_distinguisher, peer_address, peer_as, peer_bgp_id,
timestamp, version=VERSION, type_=BMP_MSG_ROUTE_MONITORING,
len_=None):
len_=None, is_adj_rib_out=False):
super(BMPRouteMonitoring,
self).__init__(peer_type=peer_type,
is_post_policy=is_post_policy,
@ -286,7 +299,8 @@ class BMPRouteMonitoring(BMPPeerMessage):
timestamp=timestamp,
len_=len_,
type_=type_,
version=version)
version=version,
is_adj_rib_out=is_adj_rib_out)
self.bgp_update = bgp_update
@classmethod
@ -308,7 +322,7 @@ class BMPRouteMonitoring(BMPPeerMessage):
@BMPMessage.register_type(BMP_MSG_STATISTICS_REPORT)
class BMPStatisticsReport(BMPPeerMessage):
"""BMP Statistics Report Message
r"""BMP Statistics Report Message
========================== ===============================================
Attribute Description
@ -335,7 +349,8 @@ class BMPStatisticsReport(BMPPeerMessage):
def __init__(self, stats, peer_type, is_post_policy, peer_distinguisher,
peer_address, peer_as, peer_bgp_id, timestamp,
version=VERSION, type_=BMP_MSG_STATISTICS_REPORT, len_=None):
version=VERSION, type_=BMP_MSG_STATISTICS_REPORT, len_=None,
is_adj_rib_out=False):
super(BMPStatisticsReport,
self).__init__(peer_type=peer_type,
is_post_policy=is_post_policy,
@ -346,7 +361,8 @@ class BMPStatisticsReport(BMPPeerMessage):
timestamp=timestamp,
len_=len_,
type_=type_,
version=version)
version=version,
is_adj_rib_out=is_adj_rib_out)
self.stats = stats
@classmethod
@ -381,7 +397,9 @@ class BMPStatisticsReport(BMPPeerMessage):
type_ == BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP:
value, = struct.unpack_from('!I', six.binary_type(value))
elif type_ == BMP_STAT_TYPE_ADJ_RIB_IN or \
type_ == BMP_STAT_TYPE_LOC_RIB:
type_ == BMP_STAT_TYPE_LOC_RIB or \
type_ == BMP_STAT_TYPE_ADJ_RIB_OUT or \
type_ == BMP_STAT_TYPE_EXPORT_RIB:
value, = struct.unpack_from('!Q', six.binary_type(value))
buf = buf[cls._MIN_LEN + len_:]
@ -410,7 +428,9 @@ class BMPStatisticsReport(BMPPeerMessage):
t == BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP:
valuepackstr = 'I'
elif t == BMP_STAT_TYPE_ADJ_RIB_IN or \
t == BMP_STAT_TYPE_LOC_RIB:
t == BMP_STAT_TYPE_LOC_RIB or \
t == BMP_STAT_TYPE_ADJ_RIB_OUT or \
t == BMP_STAT_TYPE_EXPORT_RIB:
valuepackstr = 'Q'
else:
continue
@ -424,7 +444,7 @@ class BMPStatisticsReport(BMPPeerMessage):
@BMPMessage.register_type(BMP_MSG_PEER_DOWN_NOTIFICATION)
class BMPPeerDownNotification(BMPPeerMessage):
"""BMP Peer Down Notification Message
r"""BMP Peer Down Notification Message
========================== ===============================================
Attribute Description
@ -440,7 +460,8 @@ class BMPPeerDownNotification(BMPPeerMessage):
def __init__(self, reason, data, peer_type, is_post_policy,
peer_distinguisher, peer_address, peer_as, peer_bgp_id,
timestamp, version=VERSION,
type_=BMP_MSG_PEER_DOWN_NOTIFICATION, len_=None):
type_=BMP_MSG_PEER_DOWN_NOTIFICATION, len_=None,
is_adj_rib_out=False):
super(BMPPeerDownNotification,
self).__init__(peer_type=peer_type,
@ -452,7 +473,8 @@ class BMPPeerDownNotification(BMPPeerMessage):
timestamp=timestamp,
len_=len_,
type_=type_,
version=version)
version=version,
is_adj_rib_out=is_adj_rib_out)
self.reason = reason
self.data = data
@ -498,7 +520,7 @@ class BMPPeerDownNotification(BMPPeerMessage):
@BMPMessage.register_type(BMP_MSG_PEER_UP_NOTIFICATION)
class BMPPeerUpNotification(BMPPeerMessage):
"""BMP Peer Up Notification Message
r"""BMP Peer Up Notification Message
========================== ===============================================
Attribute Description
@ -537,7 +559,7 @@ class BMPPeerUpNotification(BMPPeerMessage):
peer_type, is_post_policy, peer_distinguisher,
peer_address, peer_as, peer_bgp_id, timestamp,
version=VERSION, type_=BMP_MSG_PEER_UP_NOTIFICATION,
len_=None):
len_=None, is_adj_rib_out=False):
super(BMPPeerUpNotification,
self).__init__(peer_type=peer_type,
is_post_policy=is_post_policy,
@ -548,7 +570,8 @@ class BMPPeerUpNotification(BMPPeerMessage):
timestamp=timestamp,
len_=len_,
type_=type_,
version=version)
version=version,
is_adj_rib_out=is_adj_rib_out)
self.local_address = local_address
self.local_port = local_port
self.remote_port = remote_port
@ -605,7 +628,7 @@ class BMPPeerUpNotification(BMPPeerMessage):
@BMPMessage.register_type(BMP_MSG_INITIATION)
class BMPInitiation(BMPMessage):
"""BMP Initiation Message
r"""BMP Initiation Message
========================== ===============================================
Attribute Description
@ -669,7 +692,7 @@ class BMPInitiation(BMPMessage):
@BMPMessage.register_type(BMP_MSG_TERMINATION)
class BMPTermination(BMPMessage):
"""BMP Termination Message
r"""BMP Termination Message
========================== ===============================================
Attribute Description

View File

@ -268,7 +268,7 @@ class cc_message(operation):
self._opcode = CFM_CC_MESSAGE
assert rdi in [0, 1]
self.rdi = rdi
assert interval is not 0
assert interval != 0
self.interval = interval
self.seq_num = seq_num
assert 1 <= mep_id <= 8191

View File

@ -26,3 +26,4 @@ ETH_TYPE_LLDP = 0x88cc
ETH_TYPE_8021AH = 0x88e7
ETH_TYPE_IEEE802_3 = 0x05dc
ETH_TYPE_CFM = 0x8902
ETH_TYPE_NSH = 0x894f # RFC8300

View File

@ -75,7 +75,7 @@ BLOCK_OLD_SOURCES = 6
class icmpv6(packet_base.PacketBase):
"""ICMPv6 (RFC 2463) header encoder/decoder class.
r"""ICMPv6 (RFC 2463) header encoder/decoder class.
An instance has the following attributes at least.
Most of them are same to the on-wire counterparts but in host byte order.
@ -553,7 +553,7 @@ class nd_option_tla(nd_option_la):
@nd_router_advert.register_nd_option_type
class nd_option_pi(nd_option):
"""ICMPv6 sub encoder/decoder class for Neighbor discovery
r"""ICMPv6 sub encoder/decoder class for Neighbor discovery
Prefix Information Option. (RFC 4861)
This is used with ryu.lib.packet.icmpv6.nd_router_advert.
@ -623,6 +623,50 @@ class nd_option_pi(nd_option):
return six.binary_type(hdr)
@nd_router_advert.register_nd_option_type
class nd_option_mtu(nd_option):
"""ICMPv6 sub encoder/decoder class for Neighbor discovery
MTU Option. (RFC 4861)
This is used with ryu.lib.packet.icmpv6.nd_router_advert.
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 corresponding args in this order.
.. tabularcolumns:: |l|p{35em}|
============== ====================
Attribute Description
============== ====================
mtu MTU.
============== ====================
"""
_PACK_STR = '!BBHI'
_LEN = struct.calcsize(_PACK_STR)
_OPTION_LEN = _LEN // 8
@classmethod
def option_type(cls):
return ND_OPTION_MTU
def __init__(self, mtu=1500):
super(nd_option_mtu, self).__init__(self.option_type(), 0)
self.mtu = mtu
@classmethod
def parser(cls, buf, offset):
(_, _, _, mtu) = struct.unpack_from(cls._PACK_STR, buf, offset)
msg = cls(mtu)
return msg
def serialize(self):
buf = bytearray(struct.pack(
self._PACK_STR, self.option_type(), self._OPTION_LEN, 0, self.mtu))
return six.binary_type(buf)
@icmpv6.register_icmpv6_type(ICMPV6_ECHO_REPLY, ICMPV6_ECHO_REQUEST)
class echo(_ICMPv6Payload):
"""ICMPv6 sub encoder/decoder class for Echo Request and Echo Reply
@ -884,7 +928,7 @@ class mldv2_report(mld):
class mldv2_report_group(stringify.StringifyMixin):
"""
r"""
ICMPv6 sub encoder/decoder class for MLD v2 Lister Report Group
Record messages. (RFC 3810)

View File

@ -391,7 +391,7 @@ class igmpv3_report(igmp):
class igmpv3_report_group(stringify.StringifyMixin):
"""
r"""
Internet Group Management Protocol(IGMP, RFC 3376)
Membership Report Group Record message encoder/decoder class.

View File

@ -274,7 +274,7 @@ class dst_opts(opt_header):
class option(stringify.StringifyMixin):
"""IPv6 (RFC 2460) Options header encoder/decoder class.
r"""IPv6 (RFC 2460) Options header encoder/decoder class.
This is used with ryu.lib.packet.ipv6.hop_opts or
ryu.lib.packet.ipv6.dst_opts.
@ -496,7 +496,7 @@ class routing_type3(header):
@ipv6.register_header_type(inet.IPPROTO_FRAGMENT)
class fragment(header):
"""IPv6 (RFC 2460) fragment header encoder/decoder class.
r"""IPv6 (RFC 2460) fragment header encoder/decoder class.
This is used with ryu.lib.packet.ipv6.ipv6.

View File

@ -455,13 +455,12 @@ class SystemCapabilities(LLDPBasicTLV):
Attribute Description
================= =====================================
buf Binary data to parse.
subtype Subtype.
system_cap System Capabilities.
enabled_cap Enabled Capabilities.
================= =====================================
"""
# chassis subtype(1) + system cap(2) + enabled cap(2)
_PACK_STR = '!BHH'
# system cap(2) + enabled cap(2)
_PACK_STR = '!HH'
_PACK_SIZE = struct.calcsize(_PACK_STR)
_LEN_MIN = _PACK_SIZE
_LEN_MAX = _PACK_SIZE
@ -481,10 +480,9 @@ class SystemCapabilities(LLDPBasicTLV):
def __init__(self, buf=None, *args, **kwargs):
super(SystemCapabilities, self).__init__(buf, *args, **kwargs)
if buf:
(self.subtype, self.system_cap, self.enabled_cap) = \
struct.unpack(self._PACK_STR, self.tlv_info[:self._PACK_SIZE])
(self.system_cap, self.enabled_cap) = struct.unpack(
self._PACK_STR, self.tlv_info[:self._PACK_SIZE])
else:
self.subtype = kwargs['subtype']
self.system_cap = kwargs['system_cap']
self.enabled_cap = kwargs['enabled_cap']
self.len = self._PACK_SIZE
@ -492,9 +490,8 @@ class SystemCapabilities(LLDPBasicTLV):
self.typelen = (self.tlv_type << LLDP_TLV_TYPE_SHIFT) | self.len
def serialize(self):
return struct.pack('!HBHH',
self.typelen, self.subtype,
self.system_cap, self.enabled_cap)
return struct.pack('!HHH',
self.typelen, self.system_cap, self.enabled_cap)
@lldp.set_tlv_type(LLDP_TLV_MANAGEMENT_ADDRESS)

View File

@ -40,8 +40,16 @@ class MessageEncoder(object):
def __init__(self):
super(MessageEncoder, self).__init__()
self._packer = msgpack.Packer(encoding='utf-8', use_bin_type=True)
self._unpacker = msgpack.Unpacker(encoding='utf-8')
if msgpack.version >= (1, 0, 0):
self._packer = msgpack.Packer()
# The strict_map_key=False option is required to use int keys in
# maps; it is disabled by default to prevent hash collision denial
# of service attacks (hashdos) in scenarios where an attacker can
# control the keys to be hashed.
self._unpacker = msgpack.Unpacker(strict_map_key=False)
else:
self._packer = msgpack.Packer(encoding='utf-8', use_bin_type=True)
self._unpacker = msgpack.Unpacker(encoding='utf-8')
self._next_msgid = 0
def _create_msgid(self):

View File

@ -327,7 +327,7 @@ class StringifyMixin(object):
@classmethod
def from_jsondict(cls, dict_, decode_string=base64.b64decode,
**additional_args):
"""Create an instance from a JSON style dict.
r"""Create an instance from a JSON style dict.
Instantiate this class with parameters specified by the dict.

View File

@ -62,6 +62,10 @@ NXAST_NAT = 36
NXAST_CONTROLLER2 = 37
NXAST_SAMPLE2 = 38
NXAST_OUTPUT_TRUNC = 39
NXAST_CT_CLEAR = 43
NXAST_RAW_ENCAP = 46
NXAST_RAW_DECAP = 47
NXAST_DEC_NSH_TTL = 48
NX_ACTION_RESUBMIT_PACK_STR = '!HHIHHB3x'
NX_ACTION_RESUBMIT_SIZE = 16
@ -296,7 +300,7 @@ NXM_IP_FRAG_NOT_LATER = (0, FLOW_NW_FRAG_LATER)
def ofs_nbits(start, end):
"""
r"""
The utility method for ofs_nbits
This method is used in the class to set the ofs_nbits.
@ -590,6 +594,29 @@ tun_ipv6_dst IPv6 address Tunnel IPv6 destination address.
eth_type_nxm = 0x86dd (IPv6)
_recirc_id Integer 32bit ID for recirculation.
_dp_hash Integer 32bit Flow hash computed in Datapath.
nsh_flags Integer 8bit Flags field in NSH Base Header.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.8.
nsh_mdtype Integer 8bit Metadata Type in NSH Base Header.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.8.
nsh_np Integer 8bit Next Protocol type in NSH Base Header.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.8.
nsh_spi Integer 32bit Service Path Identifier in NSH Service Path
Header.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.8.
nsh_si Integer 8bit Service Index in NSH Service Path Header.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.8.
nsh_c<N> Integer 32bit Context fields in NSH Context Header.
<N> is a number of 1-4.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.8.
nsh_ttl Integer 8bit TTL field in NSH Base Header.
Requires eth_type_nxm = 0x894f (NSH).
Since OpenFlow 1.3 and OVS v2.9.
reg<idx> Integer 32bit Packet register.
<idx> is register number 0-15.
xxreg<idx> Integer 128bit Packet extended-extended register.
@ -684,6 +711,21 @@ oxm_types = [
# in wild.
oxm_fields.NiciraExperimenter('_dp_hash', 0, type_desc.Int4),
# Nicira Experimenter for Network Service Header
oxm_fields.NiciraNshExperimenter('nsh_flags', 1, type_desc.Int1),
oxm_fields.NiciraNshExperimenter('nsh_mdtype', 2, type_desc.Int1),
oxm_fields.NiciraNshExperimenter('nsh_np', 3, type_desc.Int1),
# aka "nsp"
oxm_fields.NiciraNshExperimenter('nsh_spi', 4, type_desc.Int4),
# aka "nsi"
oxm_fields.NiciraNshExperimenter('nsh_si', 5, type_desc.Int1),
# aka "nshc<N>"
oxm_fields.NiciraNshExperimenter('nsh_c1', 6, type_desc.Int4),
oxm_fields.NiciraNshExperimenter('nsh_c2', 7, type_desc.Int4),
oxm_fields.NiciraNshExperimenter('nsh_c3', 8, type_desc.Int4),
oxm_fields.NiciraNshExperimenter('nsh_c4', 9, type_desc.Int4),
oxm_fields.NiciraNshExperimenter('nsh_ttl', 10, type_desc.Int1),
# Support for matching/setting NX registers 0-15
oxm_fields.NiciraExtended1('reg0', 0, type_desc.Int4),
oxm_fields.NiciraExtended1('reg1', 1, type_desc.Int4),

View File

@ -248,7 +248,7 @@ def generate(ofp_name, ofpp_name):
# For OpenFlow1.0 only
class NXActionSetQueue(NXAction):
"""
r"""
Set queue action
This action sets the queue that should be used to queue
@ -338,7 +338,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionRegLoad(NXAction):
"""
r"""
Load literal value action
This action loads a literal value into a field or part of a field.
@ -405,7 +405,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionRegLoad2(NXAction):
"""
r"""
Load literal value action
This action loads a literal value into a field or part of a field.
@ -474,7 +474,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionNote(NXAction):
"""
r"""
Note action
This action does nothing at all.
@ -553,7 +553,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionSetTunnel(_NXActionSetTunnelBase):
"""
r"""
Set Tunnel action
This action sets the identifier (such as GRE) to the specified id.
@ -561,10 +561,9 @@ def generate(ofp_name, ofpp_name):
And equivalent to the followings action of ovs-ofctl command.
.. note::
ovs-ofctl command of the OpenFlow1.0 is different from that
of OpenFlow1.2 or later.
OpenFlow1.0
This actions is supported by
``OFPActionSetField``
in OpenFlow1.2 or later.
..
set_tunnel:id
@ -574,16 +573,6 @@ def generate(ofp_name, ofpp_name):
| **set_tunnel**\:\ *id* |
+------------------------+
OpenFlow1.2 or later
..
set_field:value->tun_id
..
+-----------------------------------+
| **set_field**\:\ *value*\->tun_id |
+-----------------------------------+
================ ======================================================
Attribute Description
================ ======================================================
@ -600,7 +589,7 @@ def generate(ofp_name, ofpp_name):
_fmt_str = '!2xI'
class NXActionSetTunnel64(_NXActionSetTunnelBase):
"""
r"""
Set Tunnel action
This action outputs to a port that encapsulates
@ -609,10 +598,9 @@ def generate(ofp_name, ofpp_name):
And equivalent to the followings action of ovs-ofctl command.
.. note::
ovs-ofctl command of the OpenFlow1.0 is different from that
of OpenFlow1.2 or later.
OpenFlow1.0
This actions is supported by
``OFPActionSetField``
in OpenFlow1.2 or later.
..
set_tunnel64:id
@ -622,16 +610,6 @@ def generate(ofp_name, ofpp_name):
| **set_tunnel64**\:\ *id* |
+--------------------------+
OpenFlow1.2 or later
..
set_field:value->tun_id
..
+-----------------------------------+
| **set_field**\:\ *value*\->tun_id |
+-----------------------------------+
================ ======================================================
Attribute Description
================ ======================================================
@ -648,7 +626,7 @@ def generate(ofp_name, ofpp_name):
_fmt_str = '!6xQ'
class NXActionRegMove(NXAction):
"""
r"""
Move register action
This action copies the src to dst.
@ -737,7 +715,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionResubmit(NXAction):
"""
r"""
Resubmit action
This action searches one of the switch's flow tables.
@ -786,7 +764,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionResubmitTable(NXAction):
"""
r"""
Resubmit action
This action searches one of the switch's flow tables.
@ -840,7 +818,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionOutputReg(NXAction):
"""
r"""
Add output action
This action outputs the packet to the OpenFlow port number read from
@ -914,7 +892,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionOutputReg2(NXAction):
"""
r"""
Add output action
This action outputs the packet to the OpenFlow port number read from
@ -996,7 +974,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionLearn(NXAction):
"""
r"""
Adds or modifies flow action
This action adds or modifies a flow in OpenFlow table.
@ -1260,7 +1238,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionController(NXAction):
"""
r"""
Send packet in message action
This action sends the packet to the OpenFlow controller as
@ -1325,7 +1303,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionController2(NXAction):
"""
r"""
Send packet in message action
This action sends the packet to the OpenFlow controller as
@ -1571,7 +1549,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionDecTtlCntIds(NXAction):
"""
r"""
Decrement TTL action
This action decrements TTL of IPv4 packet or
@ -1682,7 +1660,7 @@ def generate(ofp_name, ofpp_name):
# For OpenFlow1.0 only
class NXActionPushMpls(NXActionMplsBase):
"""
r"""
Push MPLS action
This action pushes a new MPLS header to the packet.
@ -1717,7 +1695,7 @@ def generate(ofp_name, ofpp_name):
# For OpenFlow1.0 only
class NXActionPopMpls(NXActionMplsBase):
"""
r"""
Pop MPLS action
This action pops the MPLS header from the packet.
@ -1752,7 +1730,7 @@ def generate(ofp_name, ofpp_name):
# For OpenFlow1.0 only
class NXActionSetMplsTtl(NXAction):
"""
r"""
Set MPLS TTL action
This action sets the MPLS TTL.
@ -1851,7 +1829,7 @@ def generate(ofp_name, ofpp_name):
# For OpenFlow1.0 only
class NXActionSetMplsLabel(NXAction):
"""
r"""
Set MPLS Lavel action
This action sets the MPLS Label.
@ -1906,7 +1884,7 @@ def generate(ofp_name, ofpp_name):
# For OpenFlow1.0 only
class NXActionSetMplsTc(NXAction):
"""
r"""
Set MPLS Tc action
This action sets the MPLS Tc.
@ -2000,7 +1978,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionStackPush(NXActionStackBase):
"""
r"""
Push field action
This action pushes field to top of the stack.
@ -2032,7 +2010,7 @@ def generate(ofp_name, ofpp_name):
_subtype = nicira_ext.NXAST_STACK_PUSH
class NXActionStackPop(NXActionStackBase):
"""
r"""
Pop field action
This action pops field from top of the stack.
@ -2064,7 +2042,7 @@ def generate(ofp_name, ofpp_name):
_subtype = nicira_ext.NXAST_STACK_POP
class NXActionSample(NXAction):
"""
r"""
Sample packets action
This action samples packets and sends one sample for
@ -2137,7 +2115,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionSample2(NXAction):
"""
r"""
Sample packets action
This action samples packets and sends one sample for
@ -2218,7 +2196,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionFinTimeout(NXAction):
"""
r"""
Change TCP timeout action
This action changes the idle timeout or hard timeout or
@ -2279,7 +2257,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionConjunction(NXAction):
"""
r"""
Conjunctive matches action
This action ties groups of individual OpenFlow flows into
@ -2342,7 +2320,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionMultipath(NXAction):
"""
r"""
Select multipath link action
This action selects multipath link based on the specified parameters.
@ -2528,7 +2506,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionBundle(_NXActionBundleBase):
"""
r"""
Select bundle link action
This action selects bundle link based on the specified parameters.
@ -2581,7 +2559,7 @@ def generate(ofp_name, ofpp_name):
ofs_nbits=0, dst=0, slaves=slaves)
class NXActionBundleLoad(_NXActionBundleBase):
"""
r"""
Select bundle link action
This action has the same behavior as the bundle action,
@ -2642,7 +2620,7 @@ def generate(ofp_name, ofpp_name):
ofs_nbits, dst, slaves)
class NXActionCT(NXAction):
"""
r"""
Pass traffic to the connection tracker action
This action sends the packet through the connection tracker.
@ -2766,8 +2744,45 @@ def generate(ofp_name, ofpp_name):
a.serialize(data, len(data))
return data
class NXActionNAT(NXAction):
class NXActionCTClear(NXAction):
"""
Clear connection tracking state action
This action clears connection tracking state from packets.
And equivalent to the followings action of ovs-ofctl command.
..
ct_clear
..
+--------------+
| **ct_clear** |
+--------------+
Example::
actions += [parser.NXActionCTClear()]
"""
_subtype = nicira_ext.NXAST_CT_CLEAR
_fmt_str = '!6x'
def __init__(self,
type_=None, len_=None, experimenter=None, subtype=None):
super(NXActionCTClear, self).__init__()
@classmethod
def parser(cls, buf):
return cls()
def serialize_body(self):
data = bytearray()
msg_pack_into(self._fmt_str, data, 0)
return data
class NXActionNAT(NXAction):
r"""
Network address translation action
This action sends the packet through the connection tracker.
@ -2930,7 +2945,7 @@ def generate(ofp_name, ofpp_name):
return data
class NXActionOutputTrunc(NXAction):
"""
r"""
Truncate output action
This action truncate a packet into the specified size and outputs it.
@ -2984,6 +2999,111 @@ def generate(ofp_name, ofpp_name):
self.max_len)
return data
class NXActionEncapEther(NXAction):
"""
Encap Ether
This action encaps package with ethernet
And equivalent to the followings action of ovs-ofctl command.
::
encap(ethernet)
Example::
actions += [parser.NXActionEncapEther()]
"""
_subtype = nicira_ext.NXAST_RAW_ENCAP
_fmt_str = '!HI'
def __init__(self,
type_=None, len_=None, vendor=None, subtype=None):
super(NXActionEncapEther, self).__init__()
self.hdr_size = 0
self.new_pkt_type = 0x00000000
@classmethod
def parser(cls, buf):
return cls()
def serialize_body(self):
data = bytearray()
msg_pack_into(self._fmt_str, data, 0, self.hdr_size, self.new_pkt_type)
return data
class NXActionEncapNsh(NXAction):
"""
Encap nsh
This action encaps package with nsh
And equivalent to the followings action of ovs-ofctl command.
::
encap(nsh(md_type=1))
Example::
actions += [parser.NXActionEncapNsh()]
"""
_subtype = nicira_ext.NXAST_RAW_ENCAP
_fmt_str = '!HI'
def __init__(self,
type_=None, len_=None, vendor=None, subtype=None):
super(NXActionEncapNsh, self).__init__()
self.hdr_size = hdr_size
self.new_pkt_type = 0x0001894F
@classmethod
def parser(cls, buf):
return cls()
def serialize_body(self):
data = bytearray()
msg_pack_into(self._fmt_str, data, 0, self.hdr_size, self.new_pkt_type)
return data
class NXActionDecNshTtl(NXAction):
"""
Decrement NSH TTL action
This action decrements the TTL in the Network Service Header(NSH).
This action was added in OVS v2.9.
And equivalent to the followings action of ovs-ofctl command.
::
dec_nsh_ttl
Example::
actions += [parser.NXActionDecNshTtl()]
"""
_subtype = nicira_ext.NXAST_DEC_NSH_TTL
_fmt_str = '!6x'
def __init__(self,
type_=None, len_=None, vendor=None, subtype=None):
super(NXActionDecNshTtl, self).__init__()
@classmethod
def parser(cls, buf):
return cls()
def serialize_body(self):
data = bytearray()
msg_pack_into(self._fmt_str, data, 0)
return data
def add_attr(k, v):
v.__module__ = ofpp.__name__ # Necessary for stringify stuff
setattr(ofpp, k, v)
@ -3026,12 +3146,16 @@ def generate(ofp_name, ofpp_name):
'NXActionBundle',
'NXActionBundleLoad',
'NXActionCT',
'NXActionCTClear',
'NXActionNAT',
'NXActionOutputTrunc',
'_NXFlowSpec', # exported for testing
'NXFlowSpecMatch',
'NXFlowSpecLoad',
'NXFlowSpecOutput',
'NXActionEncapNsh',
'NXActionEncapEther',
'NXActionDecNshTtl',
]
vars = locals()
for name in classes:

View File

@ -32,5 +32,6 @@ OFP_SSL_PORT_OLD = 6633
# Vendor/Experimenter IDs
# https://rs.opennetworking.org/wiki/display/PUBLIC/ONF+Registry
NX_EXPERIMENTER_ID = 0x00002320 # Nicira
NX_NSH_EXPERIMENTER_ID = 0x005ad650 # Nicira Ext for Network Service Header
BSN_EXPERIMENTER_ID = 0x005c16c7 # Big Switch Networks
ONF_EXPERIMENTER_ID = 0x4f4e4600 # OpenFlow Extensions for 1.3.X Pack 1

View File

@ -1258,6 +1258,8 @@ class OFPErrorMsg(MsgBase):
super(OFPErrorMsg, self).__init__(datapath)
self.type = type_
self.code = code
if isinstance(data, six.string_types):
data = data.encode('ascii')
self.data = data
@classmethod

View File

@ -141,6 +141,8 @@ class OFPErrorMsg(MsgBase):
super(OFPErrorMsg, self).__init__(datapath)
self.type = type_
self.code = code
if isinstance(data, six.string_types):
data = data.encode('ascii')
self.data = data
if self.type == ofproto.OFPET_EXPERIMENTER:
self.exp_type = kwargs.get('exp_type', None)

View File

@ -251,6 +251,8 @@ class OFPErrorMsg(MsgBase):
super(OFPErrorMsg, self).__init__(datapath)
self.type = type_
self.code = code
if isinstance(data, six.string_types):
data = data.encode('ascii')
self.data = data
if self.type == ofproto.OFPET_EXPERIMENTER:
self.exp_type = kwargs.get('exp_type', None)

View File

@ -262,6 +262,8 @@ class OFPErrorMsg(MsgBase):
super(OFPErrorMsg, self).__init__(datapath)
self.type = type_
self.code = code
if isinstance(data, six.string_types):
data = data.encode('ascii')
self.data = data
if self.type == ofproto.OFPET_EXPERIMENTER:
self.exp_type = kwargs.get('exp_type', None)

View File

@ -262,6 +262,8 @@ class OFPErrorMsg(MsgBase):
super(OFPErrorMsg, self).__init__(datapath)
self.type = type_
self.code = code
if isinstance(data, six.string_types):
data = data.encode('ascii')
self.data = data
if self.type == ofproto.OFPET_EXPERIMENTER:
self.exp_type = kwargs.get('exp_type', None)

View File

@ -132,6 +132,10 @@ class NiciraExperimenter(_Experimenter):
experimenter_id = ofproto_common.NX_EXPERIMENTER_ID
class NiciraNshExperimenter(_Experimenter):
experimenter_id = ofproto_common.NX_NSH_EXPERIMENTER_ID
class NiciraExtended0(_OxmClass):
"""Nicira Extended Match (NXM_0)

View File

@ -14,7 +14,103 @@
# limitations under the License.
"""
Defines bases classes to create a BGP application.
This module provides a convenient application for using Ryu BGPSpeaker and for
writing your BGP application.
It reads a configuration file which includes settings for neighbors, routes
and some others.
Please refer to ``ryu/services/protocols/bgp/bgp_sample_conf.py`` for the
sample configuration.
Usage Example::
$ ryu-manager ryu/services/protocols/bgp/application.py \\
--bgp-app-config-file ryu/services/protocols/bgp/bgp_sample_conf.py
SSH Console
===========
You can also use the SSH console and see the RIB and do some operations from
this console.
The SSH port and username/password can be configured by the configuration file.
You can check the help by hitting '?' key in this interface.
Example::
$ ssh localhost -p 4990
Hello, this is Ryu BGP speaker (version 4.19).
bgpd> # Hit '?' key
clear - allows to reset BGP connections
help - show this help
quit - exit this session
set - set runtime settings
show - shows runtime state information
bgpd>
bgpd> show rib all
Status codes: * valid, > best
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Labels Next Hop Reason Metric LocPrf Path
*> 10.10.1.0/24 None 0.0.0.0 Only Path i
bgpd>
Integration with Other Applications
===================================
``ryu.services.protocols.bgp.application.RyuBGPSpeaker`` will notifies the
following events to other Ryu applications.
- ``EventBestPathChanged``
- ``EventAdjRibInChanged``
- ``EventPeerDown``
- ``EventPeerUp``
To catch these events, specify ``@set_ev_cls()`` decorator to the event
handlers in the Ryu applications.
Example Application::
# my_bgp_app.py
from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from ryu.services.protocols.bgp import application as bgp_application
class MyBGPApp(app_manager.RyuApp):
_CONTEXTS = {
'ryubgpspeaker': bgp_application.RyuBGPSpeaker,
}
def __init__(self, *args, **kwargs):
super(MyBGPApp, self).__init__(*args, **kwargs)
# Stores "ryu.services.protocols.bgp.application.RyuBGPSpeaker"
# instance in order to call the APIs of
# "ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker" via
# "self.app.speaker".
# Please note at this time, "BGPSpeaker" is NOT instantiated yet.
self.app = kwargs['ryubgpspeaker']
@set_ev_cls(bgp_application.EventBestPathChanged)
def _best_patch_changed_handler(self, ev):
self.logger.info(
'Best path changed: is_withdraw=%s, path=%s',
ev.is_withdraw, ev.path)
Usage Example::
$ ryu-manager my_bgp_app.py \\
--bgp-app-config-file ryu/services/protocols/bgp/bgp_sample_conf.py
.. note::
For the APIs for ``ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker``,
please refer to :doc:`../library_bgp_speaker_ref`.
API Reference
=============
"""
import logging
@ -101,6 +197,33 @@ class EventBestPathChanged(EventBase):
self.is_withdraw = is_withdraw
class EventAdjRibInChanged(EventBase):
"""
Event called when any adj-RIB-in path is changed due to UPDATE messages
or remote peer's down.
This event is the wrapper for ``adj_rib_in_change_handler`` of
``bgpspeaker.BGPSpeaker``.
``path`` attribute contains an instance of ``info_base.base.Path``
subclasses.
If ``is_withdraw`` attribute is ``True``, ``path`` attribute has the
information of the withdraw route.
``peer_ip`` is the peer's IP address who sent this path.
``peer_as`` is the peer's AS number who sent this path.
"""
def __init__(self, path, is_withdraw, peer_ip, peer_as):
super(EventAdjRibInChanged, self).__init__()
self.path = path
self.is_withdraw = is_withdraw
self.peer_ip = peer_ip
self.peer_as = peer_as
class EventPeerDown(EventBase):
"""
Event called when the session to the remote peer goes down.
@ -140,37 +263,10 @@ class EventPeerUp(EventBase):
class RyuBGPSpeaker(RyuApp):
"""
Base application for implementing BGP applications.
This application will notifies
- ``EventBestPathChanged``
- ``EventPeerDown``
- ``EventPeerUp``
to other BGP applications.
To catch these events, specify ``@set_ev_cls()`` decorator to the event
handlers in the Ryu applications.
Example::
...
from ryu.base import app_manager
from ryu.controller.handler import set_ev_cls
from ryu.services.protocols.bgp import application as bgp_application
...
class MyBGPApp(app_manager.RyuApp):
_CONTEXTS = {
'ryubgpspeaker': bgp_application.RyuBGPSpeaker,
}
...
@set_ev_cls(bgp_application.EventBestPathChanged)
def _best_patch_changed_handler(self, ev):
self.logger.info(
'Best path changed: is_withdraw=%s, path=%s',
ev.is_withdraw, ev.path)
"""
_EVENTS = [
EventBestPathChanged,
EventAdjRibInChanged,
EventPeerDown,
EventPeerUp,
]
@ -237,6 +333,8 @@ class RyuBGPSpeaker(RyuApp):
# Set event notify handlers if no corresponding handler specified.
settings.setdefault(
'best_path_change_handler', self._notify_best_path_changed_event)
settings.setdefault(
'adj_rib_in_change_handler', self._notify_adj_rib_in_changed_event)
settings.setdefault(
'peer_down_handler', self._notify_peer_down_event)
settings.setdefault(
@ -268,6 +366,10 @@ class RyuBGPSpeaker(RyuApp):
ev = EventBestPathChanged(ev.path, ev.is_withdraw)
self.send_event_to_observers(ev)
def _notify_adj_rib_in_changed_event(self, ev, peer_ip, peer_as):
ev = EventAdjRibInChanged(ev.path, ev.is_withdraw, peer_ip, peer_as)
self.send_event_to_observers(ev)
def _notify_peer_down_event(self, remote_ip, remote_as):
ev = EventPeerDown(remote_ip, remote_as)
self.send_event_to_observers(ev)

View File

@ -68,6 +68,7 @@ from ryu.services.protocols.bgp.api.prefix import (
FLOWSPEC_FAMILY_L2VPN,
FLOWSPEC_RULES,
FLOWSPEC_ACTIONS)
from ryu.services.protocols.bgp.model import ReceivedRoute
from ryu.services.protocols.bgp.rtconf.common import LOCAL_AS
from ryu.services.protocols.bgp.rtconf.common import ROUTER_ID
from ryu.services.protocols.bgp.rtconf.common import CLUSTER_ID
@ -111,21 +112,23 @@ from ryu.services.protocols.bgp.rtconf.neighbors import (
DEFAULT_CAP_MBGP_VPNV4FS,
DEFAULT_CAP_MBGP_VPNV6FS,
DEFAULT_CAP_MBGP_L2VPNFS,
DEFAULT_CAP_ENHANCED_REFRESH,
DEFAULT_CAP_FOUR_OCTET_AS_NUMBER,
DEFAULT_CONNECT_MODE,
REMOTE_PORT,
DEFAULT_BGP_PORT,
PEER_NEXT_HOP,
PASSWORD,
DEFAULT_IS_ROUTE_SERVER_CLIENT,
IS_ROUTE_SERVER_CLIENT,
DEFAULT_IS_ROUTE_REFLECTOR_CLIENT,
IS_ROUTE_REFLECTOR_CLIENT,
DEFAULT_IS_NEXT_HOP_SELF,
IS_NEXT_HOP_SELF,
CONNECT_MODE,
LOCAL_ADDRESS,
LOCAL_PORT,
)
from ryu.services.protocols.bgp.rtconf.neighbors import (
DEFAULT_CAP_ENHANCED_REFRESH, DEFAULT_CAP_FOUR_OCTET_AS_NUMBER)
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CONNECT_MODE
from ryu.services.protocols.bgp.rtconf.neighbors import PEER_NEXT_HOP
from ryu.services.protocols.bgp.rtconf.neighbors import PASSWORD
from ryu.services.protocols.bgp.rtconf.neighbors import (
DEFAULT_IS_ROUTE_SERVER_CLIENT, IS_ROUTE_SERVER_CLIENT)
from ryu.services.protocols.bgp.rtconf.neighbors import (
DEFAULT_IS_ROUTE_REFLECTOR_CLIENT, IS_ROUTE_REFLECTOR_CLIENT)
from ryu.services.protocols.bgp.rtconf.neighbors import (
DEFAULT_IS_NEXT_HOP_SELF, IS_NEXT_HOP_SELF)
from ryu.services.protocols.bgp.rtconf.neighbors import CONNECT_MODE
from ryu.services.protocols.bgp.rtconf.neighbors import LOCAL_ADDRESS
from ryu.services.protocols.bgp.rtconf.neighbors import LOCAL_PORT
from ryu.services.protocols.bgp.rtconf.vrfs import SUPPORTED_VRF_RF
from ryu.services.protocols.bgp.info_base.base import Filter
from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
@ -220,12 +223,82 @@ class EventPrefix(object):
class BGPSpeaker(object):
"""Class to provide the APIs of Ryu BGP Speaker.
``as_number`` specifies an Autonomous Number. It must be an integer
between 1 and 65535.
``router_id`` specifies BGP router identifier. It must be the
string representation of an IPv4 address (e.g. 10.0.0.1).
``bgp_server_host`` specifies a list of TCP listen host addresses.
``bgp_server_port`` specifies TCP listen port number. 179 is
used if not specified.
``refresh_stalepath_time`` causes the BGP speaker to remove
stale routes from the BGP table after the timer expires, even
if the speaker does not receive a Router-Refresh End-of-RIB
message. This feature is disabled (not implemented yet).
``refresh_max_eor_time`` causes the BGP speaker to generate a
Route-Refresh End-of-RIB message if it was not able to
generate one due to route flapping. This feature is disabled
(not implemented yet).
``best_path_change_handler``, if specified, is called when any
best remote path is changed due to an update message or remote
peer down. The handler is supposed to take one argument, the
instance of an EventPrefix class instance.
``adj_rib_in_change_handler``, if specified, is called when any
adj-RIB-in path is changed due to an update message or remote
peer down. The given handler should take three argument, the
instance of an EventPrefix class instance, str type peer's IP address
and int type peer's AS number.
``peer_down_handler``, if specified, is called when BGP peering
session goes down.
``peer_up_handler``, if specified, is called when BGP peering
session goes up.
``ssh_console`` specifies whether or not SSH CLI need to be started.
``ssh_port`` specifies the port number for SSH CLI server.
The default is bgp.operator.ssh.DEFAULT_SSH_PORT.
``ssh_host`` specifies the IP address for SSH CLI server.
The default is bgp.operator.ssh.DEFAULT_SSH_HOST.
``ssh_host_key`` specifies the path to the host key added to
the keys list used by SSH CLI server.
The default is bgp.operator.ssh.DEFAULT_SSH_HOST_KEY.
``label_range`` specifies the range of MPLS labels generated
automatically.
``allow_local_as_in_count`` maximum number of local AS number
occurrences in AS_PATH. This option is useful for e.g. auto RD/RT
configurations in leaf/spine architecture with shared AS numbers.
The default is 0 and means "local AS number is not allowed in
AS_PATH". To allow local AS, 3 is recommended (Cisco's default).
``cluster_id`` specifies the cluster identifier for Route Reflector.
It must be the string representation of an IPv4 address.
If omitted, "router_id" is used for this field.
``local_pref`` specifies the default local preference. It must be an
integer.
"""
def __init__(self, as_number, router_id,
bgp_server_hosts=DEFAULT_BGP_SERVER_HOSTS,
bgp_server_port=DEFAULT_BGP_SERVER_PORT,
refresh_stalepath_time=DEFAULT_REFRESH_STALEPATH_TIME,
refresh_max_eor_time=DEFAULT_REFRESH_MAX_EOR_TIME,
best_path_change_handler=None,
adj_rib_in_change_handler=None,
peer_down_handler=None,
peer_up_handler=None,
ssh_console=False,
@ -234,70 +307,6 @@ class BGPSpeaker(object):
allow_local_as_in_count=0,
cluster_id=None,
local_pref=DEFAULT_LOCAL_PREF):
"""Create a new BGPSpeaker object with as_number and router_id to
listen on bgp_server_port.
``as_number`` specifies an Autonomous Number. It must be an integer
between 1 and 65535.
``router_id`` specifies BGP router identifier. It must be the
string representation of an IPv4 address (e.g. 10.0.0.1).
``bgp_server_host`` specifies a list of TCP listen host addresses.
``bgp_server_port`` specifies TCP listen port number. 179 is
used if not specified.
``refresh_stalepath_time`` causes the BGP speaker to remove
stale routes from the BGP table after the timer expires, even
if the speaker does not receive a Router-Refresh End-of-RIB
message. This feature is disabled (not implemented yet).
``refresh_max_eor_time`` causes the BGP speaker to generate a
Route-Refresh End-of-RIB message if it was not able to
generate one due to route flapping. This feature is disabled
(not implemented yet).
``best_path_change_handler``, if specified, is called when any
best remote path is changed due to an update message or remote
peer down. The handler is supposed to take one argument, the
instance of an EventPrefix class instance.
``peer_down_handler``, if specified, is called when BGP peering
session goes down.
``peer_up_handler``, if specified, is called when BGP peering
session goes up.
``ssh_console`` specifies whether or not SSH CLI need to be started.
``ssh_port`` specifies the port number for SSH CLI server.
The default is bgp.operator.ssh.DEFAULT_SSH_PORT.
``ssh_host`` specifies the IP address for SSH CLI server.
The default is bgp.operator.ssh.DEFAULT_SSH_HOST.
``ssh_host_key`` specifies the path to the host key added to
the keys list used by SSH CLI server.
The default is bgp.operator.ssh.DEFAULT_SSH_HOST_KEY.
``label_range`` specifies the range of MPLS labels generated
automatically.
``allow_local_as_in_count`` maximum number of local AS number
occurrences in AS_PATH. This option is useful for e.g. auto RD/RT
configurations in leaf/spine architecture with shared AS numbers.
The default is 0 and means "local AS number is not allowed in
AS_PATH". To allow local AS, 3 is recommended (Cisco's default).
``cluster_id`` specifies the cluster identifier for Route Reflector.
It must be the string representation of an IPv4 address.
If omitted, "router_id" is used for this field.
``local_pref`` specifies the default local preference. It must be an
integer.
"""
super(BGPSpeaker, self).__init__()
settings = {
@ -315,6 +324,7 @@ class BGPSpeaker(object):
self._core_start(settings)
self._init_signal_listeners()
self._best_path_change_handler = best_path_change_handler
self._adj_rib_in_change_handler = adj_rib_in_change_handler
self._peer_down_handler = peer_down_handler
self._peer_up_handler = peer_up_handler
if ssh_console:
@ -351,6 +361,15 @@ class BGPSpeaker(object):
if self._best_path_change_handler:
self._best_path_change_handler(ev)
def _notify_adj_rib_in_changed(self, peer, route):
if not isinstance(route, ReceivedRoute):
return
if self._adj_rib_in_change_handler:
self._adj_rib_in_change_handler(
EventPrefix(route.path, route.path.is_withdraw),
peer.ip_address, peer.remote_as)
def _init_signal_listeners(self):
CORE_MANAGER.get_core_service()._signal_bus.register_listener(
BgpSignalBus.BGP_BEST_PATH_CHANGED,
@ -358,6 +377,12 @@ class BGPSpeaker(object):
self._notify_best_path_changed(info['path'],
info['is_withdraw'])
)
CORE_MANAGER.get_core_service()._signal_bus.register_listener(
BgpSignalBus.BGP_ADJ_RIB_IN_CHANGED,
lambda _, info:
self._notify_adj_rib_in_changed(info['peer'],
info['received_route'])
)
CORE_MANAGER.get_core_service()._signal_bus.register_listener(
BgpSignalBus.BGP_ADJ_DOWN,
lambda _, info:
@ -383,6 +408,7 @@ class BGPSpeaker(object):
call('core.stop')
def neighbor_add(self, address, remote_as,
remote_port=DEFAULT_BGP_PORT,
enable_ipv4=DEFAULT_CAP_MBGP_IPV4,
enable_ipv6=DEFAULT_CAP_MBGP_IPV6,
enable_vpnv4=DEFAULT_CAP_MBGP_VPNV4,
@ -414,6 +440,8 @@ class BGPSpeaker(object):
``remote_as`` specifies the AS number of the peer. It must be
an integer between 1 and 65535.
``remote_port`` specifies the TCP port number of the peer.
``enable_ipv4`` enables IPv4 address family for this
neighbor.
@ -490,6 +518,7 @@ class BGPSpeaker(object):
bgp_neighbor = {
neighbors.IP_ADDRESS: address,
neighbors.REMOTE_AS: remote_as,
REMOTE_PORT: remote_port,
PEER_NEXT_HOP: next_hop,
PASSWORD: password,
IS_ROUTE_SERVER_CLIENT: is_route_server_client,

View File

@ -101,8 +101,16 @@ class RpcSession(Activity):
def __init__(self, sock, outgoing_msg_sink_iter):
self.peer_name = str(sock.getpeername())
super(RpcSession, self).__init__(self.NAME_FMT % self.peer_name)
self._packer = msgpack.Packer(encoding='utf-8')
self._unpacker = msgpack.Unpacker(encoding='utf-8')
if msgpack.version >= (1, 0, 0):
self._packer = msgpack.Packer()
# The strict_map_key=False option is required to use int keys in
# maps; it is disabled by default to prevent hash collision denial
# of service attacks (hashdos) in scenarios where an attacker can
# control the keys to be hashed.
self._unpacker = msgpack.Unpacker(strict_map_key=False)
else:
self._packer = msgpack.Packer(encoding='utf-8', use_bin_type=True)
self._unpacker = msgpack.Unpacker(encoding='utf-8')
self._next_msgid = 0
self._socket = sock
self._outgoing_msg_sink_iter = outgoing_msg_sink_iter

View File

@ -989,37 +989,32 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
elif self.is_route_server_client:
nlri_list = [path.nlri]
new_pathattr.extend(pathattr_map.values())
elif self.is_route_reflector_client:
nlri_list = [path.nlri]
else:
if self.is_route_reflector_client:
# Append ORIGINATOR_ID attribute if not already exist.
if BGP_ATTR_TYPE_ORIGINATOR_ID not in pathattr_map:
originator_id = path.source
if originator_id is None:
originator_id = self._common_conf.router_id
elif isinstance(path.source, Peer):
originator_id = path.source.ip_address
new_pathattr.append(
BGPPathAttributeOriginatorId(value=originator_id))
# Append ORIGINATOR_ID attribute if not already exists.
if BGP_ATTR_TYPE_ORIGINATOR_ID not in pathattr_map:
originator_id = path.source
if originator_id is None:
originator_id = self._common_conf.router_id
elif isinstance(path.source, Peer):
originator_id = path.source.ip_address
new_pathattr.append(
BGPPathAttributeOriginatorId(value=originator_id))
# Append CLUSTER_LIST attribute if not already exists.
if BGP_ATTR_TYPE_CLUSTER_LIST not in pathattr_map:
new_pathattr.append(
BGPPathAttributeClusterList(
[self._common_conf.cluster_id]))
for t, path_attr in pathattr_map.items():
if t == BGP_ATTR_TYPE_CLUSTER_LIST:
# Append own CLUSTER_ID into CLUSTER_LIST attribute
# if already exists.
cluster_list = list(path_attr.value)
# Preppend own CLUSTER_ID into CLUSTER_LIST attribute if exist.
# Otherwise append CLUSTER_LIST attribute.
cluster_lst_attr = pathattr_map.get(BGP_ATTR_TYPE_CLUSTER_LIST)
if cluster_lst_attr:
cluster_list = list(cluster_lst_attr.value)
if self._common_conf.cluster_id not in cluster_list:
cluster_list.append(self._common_conf.cluster_id)
cluster_list.insert(0, self._common_conf.cluster_id)
new_pathattr.append(
BGPPathAttributeClusterList(cluster_list))
else:
new_pathattr.append(path_attr)
else:
new_pathattr.append(
BGPPathAttributeClusterList(
[self._common_conf.cluster_id]))
# Supported and un-supported/unknown attributes.
origin_attr = None
nexthop_attr = None
@ -1288,7 +1283,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
else:
bind_addr = None
peer_address = (self._neigh_conf.ip_address,
const.STD_BGP_SERVER_PORT_NUM)
self._neigh_conf.port)
if bind_addr:
LOG.debug('%s trying to connect from'
@ -2005,8 +2000,8 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
# Open/Notification messages are currently handled by protocol and
# nothing is done inside peer, so should not see them here.
raise ValueError('Peer does not support handling of %s'
' message during % state' %
(msg, self.state.bgp_state()))
' message during %s state' %
(msg, self.state.bgp_state))
def _handle_err_sor_msg(self, afi, safi):
# Check if ERR capability is enabled for this peer.

View File

@ -45,6 +45,7 @@ from ryu.lib.packet.bgp import BGP_CAP_MULTIPROTOCOL
from ryu.lib.packet.bgp import BGP_CAP_ROUTE_REFRESH
from ryu.services.protocols.bgp.base import OrderedDict
from ryu.services.protocols.bgp.constants import STD_BGP_SERVER_PORT_NUM
from ryu.services.protocols.bgp.rtconf.base import ADVERTISE_PEER_AS
from ryu.services.protocols.bgp.rtconf.base import BaseConf
from ryu.services.protocols.bgp.rtconf.base import BaseConfListener
@ -88,6 +89,7 @@ LOG = logging.getLogger('bgpspeaker.rtconf.neighbor')
# Various neighbor settings.
REMOTE_AS = 'remote_as'
IP_ADDRESS = 'ip_address'
REMOTE_PORT = 'remote_port'
ENABLED = 'enabled'
CHANGES = 'changes'
LOCAL_ADDRESS = 'local_address'
@ -108,6 +110,7 @@ CONNECT_MODE_PASSIVE = 'passive'
CONNECT_MODE_BOTH = 'both'
# Default value constants.
DEFAULT_BGP_PORT = STD_BGP_SERVER_PORT_NUM
DEFAULT_CAP_GR_NULL = True
DEFAULT_CAP_REFRESH = True
DEFAULT_CAP_ENHANCED_REFRESH = False
@ -213,6 +216,13 @@ def validate_remote_as(asn):
return asn
@validate(name=REMOTE_PORT)
def validate_remote_port(port):
if not isinstance(port, numbers.Integral):
raise ConfigTypeError(desc='Invalid remote port: %s' % port)
return port
def valid_prefix_filter(filter_):
policy = filter_.get('policy', None)
if policy == 'permit':
@ -339,7 +349,7 @@ class NeighborConf(ConfWithId, ConfWithStats):
CAP_MBGP_IPV4FS, CAP_MBGP_VPNV4FS,
CAP_MBGP_IPV6FS, CAP_MBGP_VPNV6FS,
CAP_MBGP_L2VPNFS,
RTC_AS, HOLD_TIME,
RTC_AS, HOLD_TIME, REMOTE_PORT,
ENABLED, MULTI_EXIT_DISC, MAX_PREFIXES,
ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
LOCAL_ADDRESS, LOCAL_PORT, LOCAL_AS,
@ -406,6 +416,8 @@ class NeighborConf(ConfWithId, ConfWithStats):
DEFAULT_IS_NEXT_HOP_SELF, **kwargs)
self._settings[CONNECT_MODE] = compute_optional_conf(
CONNECT_MODE, DEFAULT_CONNECT_MODE, **kwargs)
self._settings[REMOTE_PORT] = compute_optional_conf(
REMOTE_PORT, DEFAULT_BGP_PORT, **kwargs)
# We do not have valid default MED value.
# If no MED attribute is provided then we do not have to use MED.
@ -483,6 +495,10 @@ class NeighborConf(ConfWithId, ConfWithStats):
def ip_address(self):
return self._settings[IP_ADDRESS]
@property
def port(self):
return self._settings[REMOTE_PORT]
@property
def host_bind_ip(self):
return self._settings[LOCAL_ADDRESS]

View File

@ -319,7 +319,7 @@ class RemoteOvsdb(app_manager.RyuApp):
fsm.connected(now())
session = jsonrpc.Session(fsm, connection)
session = jsonrpc.Session(fsm, connection, fsm.get_name())
idl = Idl(session, schemas[0])
system_id = discover_system_id(idl)

View File

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""
r"""
Usage:
PYTHONPATH=. ./bin/ryu-manager --verbose \
ryu.services.protocols.vrrp.dumper \

View File

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""
r"""
Usage:
PYTHONPATH=. ./bin/ryu-manager --verbose \
ryu.topology.switches \

View File

@ -131,6 +131,13 @@ MESSAGES = [
'importance=39032'] +
['dl_type=0x86dd'] +
['actions=ct(commit,nat(dst=2001:1::1-2001:1::ffff)'])},
{'name': 'action_ct_clear',
'versions': [4],
'cmd': 'add-flow',
'args': (['table=3,',
'importance=39032'] +
['dl_type=0x0800,ct_state=+trk'] +
['actions=ct_clear'])},
{'name': 'action_note',
'versions': [4],
'cmd': 'add-flow',
@ -312,7 +319,7 @@ if __name__ == '__main__':
stdout=subprocess.PIPE)
has_names = False
try:
ver_tuple = re.search('\s(\d+)\.(\d+)(\.\d*|\s*$)',
ver_tuple = re.search(r'\s(\d+)\.(\d+)(\.\d*|\s*$)',
ovs_version.stdout.readline().decode()).groups()
if int(ver_tuple[0]) > 2 or \
int(ver_tuple[0]) == 2 and int(ver_tuple[1]) >= 8:

View File

@ -62,12 +62,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]
@ -135,13 +135,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]
@ -245,12 +245,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]
@ -353,12 +353,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]

View File

@ -62,12 +62,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -135,13 +135,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -245,12 +245,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -353,12 +353,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]

View File

@ -52,12 +52,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -115,12 +115,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -238,13 +238,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -303,13 +303,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -464,12 +464,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -564,12 +564,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -759,12 +759,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -858,12 +858,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]

View File

@ -52,12 +52,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -115,12 +115,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -238,13 +238,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -303,13 +303,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -464,12 +464,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -564,12 +564,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -759,12 +759,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -858,12 +858,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]

View File

@ -62,12 +62,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]
@ -135,13 +135,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]
@ -245,12 +245,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]
@ -353,12 +353,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=135)"
]
}
]

View File

@ -62,12 +62,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -135,13 +135,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -245,12 +245,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -353,12 +353,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=1,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=1,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]

View File

@ -52,12 +52,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -115,12 +115,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -238,13 +238,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -303,13 +303,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -464,12 +464,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -564,12 +564,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -759,12 +759,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -858,12 +858,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]

View File

@ -52,12 +52,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -115,12 +115,12 @@
"ingress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -238,13 +238,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -303,13 +303,13 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=33024)",
"vlan(pcp=3, cfi=0, vid=100, ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -464,12 +464,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -564,12 +564,12 @@
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34887)",
"mpls(bsb=1, label=100, exp=3, ttl=64)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -759,12 +759,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"egress":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]
@ -858,12 +858,12 @@
"itag(sid=100)",
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
],
"PACKET_IN":[
"ethernet(dst='22:22:22:22:22:22', src='12:11:11:11:11:11', ethertype=34525)",
"ipv6(dst='20::20', flow_label=100, src='10::10', nxt=58, hop_limit=64, traffic_class=32)",
"icmpv6(code=0,data=echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
"icmpv6(code=0,data=icmpv6echo(data=b'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123'),type_=128)"
]
}
]

View File

@ -47,13 +47,31 @@ from ryu.ofproto import ofproto_v1_5
# import all packet libraries.
PKT_LIB_PATH = 'ryu.lib.packet'
CLSNAME_ALIASES = {
('ryu.lib.packet.ipv6', 'option'): 'ipv6option',
('ryu.lib.packet.icmpv6', 'echo'): 'icmpv6echo',
('ryu.lib.packet.bgp', 'StreamParser'): '',
('ryu.lib.packet.bgp', 'StringifyMixin'): '',
('ryu.lib.packet.dhcp', 'option'): 'dhcpoption',
('ryu.lib.packet.dhcp', 'options'): 'dhcpoptions',
('ryu.lib.packet.ospf', 'StringifyMixin'): ''
}
for modname, moddef in sys.modules.items():
if not modname.startswith(PKT_LIB_PATH) or not moddef:
continue
for (clsname, clsdef, ) in inspect.getmembers(moddef):
if not inspect.isclass(clsdef):
continue
exec('from %s import %s' % (modname, clsname))
clsname_alias = CLSNAME_ALIASES.get((modname, clsname))
if clsname_alias == '':
continue
elif clsname_alias is not None:
exec('from %s import %s as %s' % (modname, clsname, clsname_alias))
else:
assert clsname not in globals(), (
"%s.%s already defined" % (modname, clsname))
exec('from %s import %s' % (modname, clsname))
""" Required test network:

View File

@ -267,6 +267,8 @@ def add_method(cls, method_name, method):
method.__name__ = method_name
if six.PY3:
methodtype = types.MethodType(method, cls)
if not hasattr(method, "__qualname__"):
method.__qualname__ = "%s.%s" % (cls.__qualname__, method_name)
else:
methodtype = types.MethodType(method, None, cls)
setattr(cls, method_name, methodtype)

View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDaDCCAlCgAwIBAgIJAKL09YuU92JPMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNV
BAYTAkpQMRMwEQYDVQQIDApTb21lLVN0YXRlMSQwIgYDVQQKDBtSeXUgU0ROIEZy
YW1ld29yayBDb21tdW5pdHkwIBcNMTkwMzI1MDE1NzQzWhgPMjI5MzAxMDYwMTU3
NDNaMEgxCzAJBgNVBAYTAkpQMRMwEQYDVQQIDApTb21lLVN0YXRlMSQwIgYDVQQK
DBtSeXUgU0ROIEZyYW1ld29yayBDb21tdW5pdHkwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDLT29+6JwD75wH7gPVxU52hrysBfxE6WjyT/nT+aSIQmZu
SU6/5hECOnV4YdyB7rxFu2WO2SD5PgeoHPBpTqtxrdTWoVOWVljnNcqEwSCS7bl9
nbgX8uxCacg9qbFNJJRBAS0XQ2bSsD0GoOnhj3Olrz1u0wRIUqrR3A5giMbYwQPr
S4cmkxfgp2uV+WCHk40WxZnGgWzIRhO11GK9CAGncncPYhj+23w+GFaHIf00TdV2
JEvwLFuLf1EaewZ7rz8zf1sLHAxqx20A6VdledEpNAzt1L8goPhk1mHvRgUC7E2v
FnSt1ePCJsVrvccudMdPBXSMfgJC2gmfdQefdSXRAgMBAAGjUzBRMB0GA1UdDgQW
BBRjlXSQ2rVjwOr1io6iJyidmjCNfzAfBgNVHSMEGDAWgBRjlXSQ2rVjwOr1io6i
JyidmjCNfzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCC1Uvo
4PdC5YQSXkAhrxgVhexp87VVkoWwpno75hvfoCjtSkb7+cskvQbPM14zbjIUrsli
qmTkjXyTUe8q5U06OitMAyM6qUvS0nFDi5aPQYV6N0XmJ+rV18prfQORyHvEmEyv
nqHVPoQkmGPpJ8aOVrTlECyxG7wLI2UxBEB3Atk51QHzbGGLKW7g5tHY6J5cMe/9
ydeClJk2/AXkoqWkbtJrbw46alH97CajuLn/4D9B/Rm+M1Kg48gze5zJ7+WrB0Jl
pAhRqMM3upaOlXdeYDdNDgE0j/ulZGY2UssFIoHylcrb4QKQXjwqRXYhuuucJQJ3
vsY4y1D/qps9llRL
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDLT29+6JwD75wH
7gPVxU52hrysBfxE6WjyT/nT+aSIQmZuSU6/5hECOnV4YdyB7rxFu2WO2SD5Pgeo
HPBpTqtxrdTWoVOWVljnNcqEwSCS7bl9nbgX8uxCacg9qbFNJJRBAS0XQ2bSsD0G
oOnhj3Olrz1u0wRIUqrR3A5giMbYwQPrS4cmkxfgp2uV+WCHk40WxZnGgWzIRhO1
1GK9CAGncncPYhj+23w+GFaHIf00TdV2JEvwLFuLf1EaewZ7rz8zf1sLHAxqx20A
6VdledEpNAzt1L8goPhk1mHvRgUC7E2vFnSt1ePCJsVrvccudMdPBXSMfgJC2gmf
dQefdSXRAgMBAAECggEAcvPsB6Z/qB4Pa9Bg7LqNnaia/uy3cUND6lXb3MW3CK/6
eHsMgqYTkd3502IJqpGQdCD70CPmZ+Zxr9UE/ZXUjAcMY3p952/U/o3EfwEvaMPu
8B6AG1Jn0Tk8VdkffY2kIYkHtLKQbanmJ1xOQRG6AsEti/7V2gqbuOKiYmSTgbPG
Upw9JNdtR6bZrGrrEXJbPCrSCej47MDyE+nt4zMIsqmY5IlbTMHcTKVDGeKbT9qT
7/Uyg+Tb62eber9iQhE0OteLt2GwrJR5yZ5QKNKM4SPqwYlOvQ9z289eZMVU3uwI
1NI1YRM5EMsdWrzFye7H/T/jsCaWrO0zmI/I4BMfEQKBgQDtUgPyY4PgVXVZ/hha
l5pi66GQ79+6LJP3SHb3I6p0iULq3oV+onG0Ezvx2vc21sbuLEazNlJoXzEzSIVM
/RjNJ9FsD/ENEuJedkspwtZZ4O4ZH6wKyHg/LCUly59ER37Ql/XwIX7adKCn7Z4d
9xN3aQmPtLna/aIZ8HyptRpT9QKBgQDbUB67YXiIFY+k5cwtK0m8T3rY4WNpEwzr
Y/1l+0EvXqCousU9MnLveyY8EcLDh5SnM0CvH4mFS8xL/r/kcUO9cHwuM+KZ77KN
Ukp9CRT9raxDZY/F0FVuET4LrJNnekCMsOnMxO51il/AHcul7886sEirkB1dsXND
nkh9h8g87QJ/cRikyN6j+kS/qCNvd7zH1lx0op2uAQs9eJsQFrbohKDlQwjIlZDU
nvyLlLbFGV1BcD+pcb5xh0vWJppo7EexihNvug/e0FwvhNTa/QvdGvgWf+KYGotu
wqxHB7wCKofn54CDs+xCh9kMtvqGX8FfhYiJBfMan0I//hydTEMCSQKBgEiv6E+g
gYtQ4hf8FczOsRSZnxSstv8HUlvd+wlG2hbyHPtvU5nx04gt38E+/bdCg3FbGlAw
eqrUMXTqjP0Q0SvDUVUa2zq76AjQwmFoli1x10tLKPieEQJ28oJ6Ayzjpus6Y3L7
vjD02MFa3rkznxJLhPpfvGvmOVaq6km4rBQNAoGBALQGfaRiAtp6lSubi4Etdwtg
Tps2o1SBXfzENpq6s99k+UdCBLh90uzuA897GClsUYeuAYUyxQP3otIZUuSjq/Ht
JHYwT9QxOkSYrNCfQW/nF0CJjZ6TcvcFp8SdyUUbwCR2rkDK7LlMzxkfU3cCrwMP
q51oIVlKjIxg86JJXrRQ
-----END PRIVATE KEY-----

View File

@ -22,6 +22,7 @@ except ImportError:
import json
import os
import ssl
import sys
import warnings
import logging
@ -33,9 +34,11 @@ from nose.tools import eq_, raises
from ryu.base import app_manager # To suppress cyclic import
from ryu.controller import controller
from ryu.controller import handler
from ryu.lib import hub
from ryu.ofproto import ofproto_v1_3_parser
from ryu.ofproto import ofproto_v1_2_parser
from ryu.ofproto import ofproto_v1_0_parser
hub.patch()
LOG = logging.getLogger('test_controller')
@ -177,3 +180,53 @@ class Test_Datapath(unittest.TestCase):
self.assertEqual(state, handler.MAIN_DISPATCHER)
self.assertEqual(kwargs, {})
self.assertEqual(expected_json, output_json)
class TestOpenFlowController(unittest.TestCase):
"""
Test cases for OpenFlowController
"""
@mock.patch("ryu.controller.controller.CONF")
def _test_ssl(self, this_dir, port, conf_mock):
conf_mock.ofp_ssl_listen_port = port
conf_mock.ofp_listen_host = "127.0.0.1"
conf_mock.ca_certs = None
conf_mock.ciphers = None
conf_mock.ctl_cert = os.path.join(this_dir, 'cert.crt')
conf_mock.ctl_privkey = os.path.join(this_dir, 'cert.key')
c = controller.OpenFlowController()
c()
def test_ssl(self):
"""Tests SSL server functionality."""
# TODO: TLS version enforcement is necessary to avoid
# vulnerable versions. Currently, this only tests TLS
# connectivity.
this_dir = os.path.dirname(sys.modules[__name__].__file__)
saved_exception = None
try:
ssl_version = ssl.PROTOCOL_TLS
except AttributeError:
# For compatibility with older pythons.
ssl_version = ssl.PROTOCOL_TLSv1
for i in range(3):
try:
# Try a few times as this can fail with EADDRINUSE
port = random.randint(5000, 10000)
server = hub.spawn(self._test_ssl, this_dir, port)
hub.sleep(1)
client = hub.StreamClient(("127.0.0.1", port),
timeout=5,
ssl_version=ssl_version)
if client.connect() is not None:
break
except Exception as e:
saved_exception = e
continue
finally:
try:
hub.kill(server)
except Exception:
pass
else:
self.fail("Failed to connect: " + str(saved_exception))

View File

@ -35,7 +35,7 @@ LOG = logging.getLogger(__name__)
DOCKER_IMAGE_MININET = 'osrg/ryu-book'
OVSDB_MANAGER_ADDR = 'ptcp:6640'
OVSDB_SWITCH_ADDR = 'tcp:%s:6640'
OVSDB_SWITCH_ADDR = 'tcp:0.0.0.0:6640'
def setUpModule():
@ -93,7 +93,7 @@ class TestVSCtl(unittest.TestCase):
@classmethod
def _docker_run(cls, image):
return _run('docker run --privileged -t -d %s' % image)[0]
return _run('docker run --privileged -t -d -p 6640:6640 %s' % image)[0]
@classmethod
def _docker_stop(cls, container):
@ -124,7 +124,7 @@ class TestVSCtl(unittest.TestCase):
@classmethod
def _set_up_vsctl(cls):
cls.vsctl = vsctl.VSCtl(OVSDB_SWITCH_ADDR % cls.container_mn_ip)
cls.vsctl = vsctl.VSCtl(OVSDB_SWITCH_ADDR)
@classmethod
def setUpClass(cls):

View File

@ -19,6 +19,7 @@ import bz2
import io
import logging
import os
import struct
import sys
import unittest
@ -609,6 +610,66 @@ class TestMrtlibMrtPeer(unittest.TestCase):
eq_(buf, output)
class TestMrtlibMrtRibEntry(unittest.TestCase):
"""
Test case for ryu.lib.mrtlib.MrtRibEntry.
"""
def test_parse_add_path(self):
peer_index = 1
originated_time = 2
nexthop = '1.1.1.1'
bgp_attribute = bgp.BGPPathAttributeNextHop(nexthop)
path_id = 3
bgp_attr_buf = bgp_attribute.serialize()
attr_len = len(bgp_attr_buf)
buf = (
b'\x00\x01' # peer_index
b'\x00\x00\x00\x02' # originated_time
b'\x00\x00\x00\x03' # path_id
+ struct.pack('!H', attr_len) # attr_len
+ bgp_attribute.serialize() # bgp_attributes
)
rib, rest = mrtlib.MrtRibEntry.parse(buf, is_addpath=True)
eq_(peer_index, rib.peer_index)
eq_(originated_time, rib.originated_time)
eq_(path_id, rib.path_id)
eq_(attr_len, rib.attr_len)
eq_(1, len(rib.bgp_attributes))
eq_(nexthop, rib.bgp_attributes[0].value)
eq_(b'', rest)
def test_serialize_add_path(self):
peer_index = 1
originated_time = 2
nexthop = '1.1.1.1'
bgp_attribute = bgp.BGPPathAttributeNextHop(nexthop)
path_id = 3
bgp_attr_buf = bgp_attribute.serialize()
attr_len = len(bgp_attr_buf)
buf = (
b'\x00\x01' # peer_index
b'\x00\x00\x00\x02' # originated_time
b'\x00\x00\x00\x03' # path_id
+ struct.pack('!H', attr_len) # attr_len
+ bgp_attribute.serialize() # bgp_attributes
)
rib = mrtlib.MrtRibEntry(
peer_index=peer_index,
originated_time=originated_time,
bgp_attributes=[bgp_attribute],
# attr_len=attr_len,
path_id=path_id,
)
output = rib.serialize()
eq_(buf, output)
class TestMrtlibBgp4MpMrtRecord(unittest.TestCase):
"""
Test case for ryu.lib.mrtlib.Bgp4MpMrtRecord.

View File

@ -413,7 +413,7 @@ class Test_ofctl(unittest.TestCase):
# without mask
eq_(eth, field_value)
return
elif key in['nw_src', 'nw_dst', 'arp_spa', 'arp_tpa']:
elif key in ['nw_src', 'nw_dst', 'arp_spa', 'arp_tpa']:
# IPv4 address
if test.ver == ofproto_v1_0.OFP_VERSION:
ipv4, mask = _to_match_ip(value)

View File

@ -138,13 +138,18 @@ class Test_rpc(unittest.TestCase):
assert result == obj
assert isinstance(result, numbers.Integral)
@raises(TypeError)
def test_0_call_bytearray(self):
c = rpc.Client(self._client_sock)
obj = bytearray(b'foo')
result = c.call('resp', [obj])
assert result == obj
assert isinstance(result, str)
# Note: msgpack-python version 0.50 or later supports bytearray
# objects, here ignores TypeError for the backward compatibility.
try:
result = c.call('resp', [obj])
except TypeError:
# Case with msgpack-python version 0.4.x or earlier.
return
self.assertEqual(obj, result)
self.assertIsInstance(result, six.binary_type)
def test_1_shutdown_wr(self):
# test if the server shutdown on disconnect

View File

@ -0,0 +1,55 @@
{
"OFPFlowMod": {
"buffer_id": 4294967295,
"command": 0,
"cookie": 0,
"cookie_mask": 0,
"flags": 0,
"hard_timeout": 0,
"idle_timeout": 0,
"instructions": [
{
"OFPInstructionActions": {
"actions": [
{
"NXActionCTClear": {
"experimenter": 8992,
"len": 16,
"subtype": 43,
"type": 65535
}
}
],
"len": 24,
"type": 4
}
}
],
"match": {
"OFPMatch": {
"length": 22,
"oxm_fields": [
{
"OXMTlv": {
"field": "eth_type",
"mask": null,
"value": 2048
}
},
{
"OXMTlv": {
"field": "ct_state",
"mask": 32,
"value": 32
}
}
],
"type": 1
}
},
"out_group": 4294967295,
"out_port": 4294967295,
"priority": 32768,
"table_id": 3
}
}

View File

@ -54,12 +54,31 @@ class Test_bmp(unittest.TestCase):
eq_(msg.to_jsondict(), msg2.to_jsondict())
eq_(rest, b'')
def test_route_monitoring_adj_rib_out(self):
update = bgp.BGPUpdate()
msg = bmp.BMPRouteMonitoring(bgp_update=update,
peer_type=bmp.BMP_PEER_TYPE_GLOBAL,
is_post_policy=True,
is_adj_rib_out=True,
peer_distinguisher=0,
peer_address='192.0.2.1',
peer_as=30000,
peer_bgp_id='192.0.2.1',
timestamp=self._time())
binmsg = msg.serialize()
msg2, rest = bmp.BMPMessage.parser(binmsg)
eq_(msg.to_jsondict(), msg2.to_jsondict())
eq_(rest, b'')
def test_statistics_report(self):
stats = [{'type': bmp.BMP_STAT_TYPE_REJECTED, 'value': 100},
{'type': bmp.BMP_STAT_TYPE_DUPLICATE_PREFIX, 'value': 200},
{'type': bmp.BMP_STAT_TYPE_DUPLICATE_WITHDRAW, 'value': 300},
{'type': bmp.BMP_STAT_TYPE_ADJ_RIB_IN, 'value': 100000},
{'type': bmp.BMP_STAT_TYPE_LOC_RIB, 'value': 500000}]
{'type': bmp.BMP_STAT_TYPE_LOC_RIB, 'value': 500000},
{'type': bmp.BMP_STAT_TYPE_ADJ_RIB_OUT, 'value': 95000},
{'type': bmp.BMP_STAT_TYPE_EXPORT_RIB, 'value': 50000},
{'type': bmp.BMP_STAT_TYPE_EXPORT_RIB, 'value': 50000}]
msg = bmp.BMPStatisticsReport(stats=stats,
peer_type=bmp.BMP_PEER_TYPE_GLOBAL,
is_post_policy=True,

View File

@ -227,8 +227,7 @@ class TestLLDPOptionalTLV(unittest.TestCase):
+ b'\x73\x74\x65\x72\x20\x30\x35\x2f' \
+ b'\x32\x37\x2f\x30\x35\x20\x30\x34' \
+ b'\x3a\x35\x33\x3a\x31\x31\x00\x0e' \
+ b'\x05\x01\x00\x14\x00\x14\x10\x0e' \
+ b'\x07' \
+ b'\x04\x00\x14\x00\x14\x10\x0e\x07' \
+ b'\x06\x00\x01\x30\xf9\xad\xa0\x02' \
+ b'\x00\x00\x03\xe9\x00\xfe\x07\x00' \
+ b'\x12\x0f\x02\x07\x01\x00\xfe\x09' \
@ -274,7 +273,6 @@ class TestLLDPOptionalTLV(unittest.TestCase):
# SystemCapabilities
eq_(tlvs[6].tlv_type, lldp.LLDP_TLV_SYSTEM_CAPABILITIES)
eq_(tlvs[6].subtype, lldp.ChassisID.SUB_CHASSIS_COMPONENT)
eq_(tlvs[6].system_cap & lldp.SystemCapabilities.CAP_MAC_BRIDGE,
lldp.SystemCapabilities.CAP_MAC_BRIDGE)
eq_(tlvs[6].enabled_cap & lldp.SystemCapabilities.CAP_MAC_BRIDGE,
@ -322,7 +320,6 @@ class TestLLDPOptionalTLV(unittest.TestCase):
system_description=b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ b'by Release_Master 05/27/05 04:53:11\x00')
tlv_system_capabilities = lldp.SystemCapabilities(
subtype=lldp.ChassisID.SUB_CHASSIS_COMPONENT,
system_cap=0x14,
enabled_cap=0x14)
tlv_management_address = lldp.ManagementAddress(
@ -360,7 +357,6 @@ class TestLLDPOptionalTLV(unittest.TestCase):
system_description=b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ b'by Release_Master 05/27/05 04:53:11\x00')
sys_cap = lldp.SystemCapabilities(
subtype=lldp.ChassisID.SUB_CHASSIS_COMPONENT,
system_cap=0x14,
enabled_cap=0x14)
man_addr = lldp.ManagementAddress(
@ -434,8 +430,7 @@ class TestLLDPOptionalTLV(unittest.TestCase):
_sys_desc_str)
# SystemCapabilities string
sys_cap_values = {'subtype': lldp.ChassisID.SUB_CHASSIS_COMPONENT,
'system_cap': 0x14,
sys_cap_values = {'system_cap': 0x14,
'enabled_cap': 0x14,
'len': sys_cap.len,
'typelen': sys_cap.typelen}
@ -515,7 +510,6 @@ class TestLLDPOptionalTLV(unittest.TestCase):
system_description=b'Summit300-48 - Version 7.4e.1 (Build 5) '
+ b'by Release_Master 05/27/05 04:53:11\x00')
sys_cap = lldp.SystemCapabilities(
subtype=lldp.ChassisID.SUB_CHASSIS_COMPONENT,
system_cap=0x14,
enabled_cap=0x14)
man_addr = lldp.ManagementAddress(

View File

@ -1,86 +0,0 @@
# Copyright (C) 2016 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 logging
import os
import sys
import unittest
import pkg_resources
from pip.req import parse_requirements
from pip.download import PipSession
from six.moves import urllib
from nose.tools import ok_
LOG = logging.getLogger(__name__)
MOD_DIR = os.path.dirname(sys.modules[__name__].__file__)
_RYU_REQUIREMENTS_FILES = [
'../../../tools/pip-requires',
'../../../tools/optional-requires',
]
RYU_REQUIREMENTS_FILES = [
os.path.join(MOD_DIR, f) for f in _RYU_REQUIREMENTS_FILES]
OPENSTACK_REQUIREMENTS_REPO = 'https://github.com/openstack/requirements'
OPENSTACK_REQUIREMENTS_URL = (
'https://github.com/openstack/requirements/raw/master/')
_OPENSTACK_REQUIREMENTS_FILES = [
'requirements.txt',
'global-requirements.txt',
]
OPENSTACK_REQUIREMENTS_FILES = [
urllib.parse.urljoin(OPENSTACK_REQUIREMENTS_URL, f)
for f in _OPENSTACK_REQUIREMENTS_FILES]
def _get_requirements(files):
requirements = {}
for f in files:
req = parse_requirements(f, session=PipSession())
for r in req:
requirements[r.name] = str(r.req)
return requirements
OPENSTACK_REQUIREMENTS = _get_requirements(OPENSTACK_REQUIREMENTS_FILES)
RYU_REQUIREMENTS = _get_requirements(RYU_REQUIREMENTS_FILES)
class TestRequirements(unittest.TestCase):
"""
Test whether the requirements of Ryu has no conflict with that
of other projects.
"""
def setUp(self):
pass
def tearDown(self):
pass
def test_with_openstack_requirements(self):
try:
for name, req in OPENSTACK_REQUIREMENTS.items():
if name in RYU_REQUIREMENTS:
ok_(pkg_resources.require(req))
except pkg_resources.VersionConflict as e:
LOG.exception(
'Some requirements of Ryu are conflicting with that of '
'OpenStack project: %s' % OPENSTACK_REQUIREMENTS_REPO)
raise e

View File

@ -126,34 +126,3 @@ def binary_str(data):
"""
# convert data into bytearray explicitly
return ''.join('\\x%02x' % byte for byte in bytearray(data))
def parse_requirements(requirements_files=None):
"""
Parses requirements files and returns a list of requirements.
Returned list would be like::
['foo', 'bar>=X.X', ...]
:param requirements_files: List of requirements files. The default
is ['requirements.txt', 'tools/pip-requires'].
:return: List of requirements.
"""
from pip import req as pip_req
from pip.download import PipSession
requirements_files = requirements_files or [
'requirements.txt',
'tools/pip-requires',
]
requirements = []
for f in requirements_files:
if not os.path.isfile(f):
continue
for r in pip_req.parse_requirements(f, session=PipSession()):
requirements.append(str(r.req))
return requirements

View File

@ -4,7 +4,7 @@ summary = Component-based Software-defined Networking Framework
license = Apache License 2.0
author = Ryu project team
author-email = ryu-devel@lists.sourceforge.net
home-page = http://osrg.github.io/ryu/
home-page = https://ryu-sdn.org
description-file = README.rst
platform = any
classifier =
@ -13,9 +13,12 @@ classifier =
Topic :: System :: Networking
Natural Language :: English
Programming Language :: Python
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Operating System :: Unix
keywords =
openflow

View File

@ -14,12 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# a bug workaround. http://bugs.python.org/issue15881
try:
import multiprocessing
except ImportError:
pass
import setuptools
import ryu.hooks

View File

@ -70,29 +70,29 @@ def check_dependencies():
if not HAS_VIRTUALENV:
raise Exception('Virtualenv not found. ' + \
'Try installing python-virtualenv')
print 'done.'
print('done.') # pylint: disable=print-statement
def create_virtualenv(venv=VENV, install_pip=False):
"""Creates the virtual environment and installs PIP only into the
virtual environment
"""
print 'Creating venv...',
print('Creating venv...') # pylint: disable=print-statement
install = ['virtualenv', '-q', venv]
run_command(install)
print 'done.'
print 'Installing pip in virtualenv...',
print('done.') # pylint: disable=print-statement
print('Installing pip in virtualenv...') # pylint: disable=print-statement
if install_pip and \
not run_command(['tools/with_venv.sh', 'easy_install',
'pip>1.0']):
die("Failed to install pip.")
print 'done.'
print('done.') # pylint: disable=print-statement
def install_dependencies(venv=VENV):
print 'Installing dependencies with pip (this can take a while)...'
print('Installing dependencies with pip (this can take a while)...') # pylint: disable=print-statement
run_command(['tools/with_venv.sh', 'pip', 'install', '-r',
PIP_REQUIRES], redirect_output=False)
run_command(['tools/with_venv.sh', 'pip', 'install', '-r',
@ -126,7 +126,7 @@ def print_help():
Also, make test will automatically use the virtualenv.
"""
print help
print(help) # pylint: disable=print-statement
def main(argv):

View File

@ -1,12 +1,12 @@
# NOTE: OpenStack avoids the newer versions of eventlet, because of the
# NOTE: OpenStack avoids some versions of eventlet, because of the
# following issue.
# https://github.com/eventlet/eventlet/issues/401
eventlet!=0.18.3,>=0.18.2,!=0.20.1,<0.21.0
msgpack-python>=0.3.0 # RPC library, BGP speaker(net_cntl)
eventlet==0.30.0
msgpack>=0.4.0 # RPC library, BGP speaker(net_cntl)
netaddr
oslo.config>=1.15.0
oslo.config>=2.5.0
ovs>=2.6.0 # OVSDB
routes # wsgi
six>=1.4.0
tinyrpc # RPC library, BGP speaker(net_cntl)
tinyrpc==0.9.4 # RPC library, BGP speaker(net_cntl)
webob>=1.2 # wsgi

22
tox.ini
View File

@ -1,5 +1,13 @@
[tox]
envlist = py27,py34,py35,pypy26,pycodestyle,autopep8
envlist = py35,py36,py37,py38,py39,pypy,pycodestyle,autopep8
[gh-actions]
python =
3.5: py35
3.6: py36, pycodestyle, autopep8
3.7: py37
3.8: py38
3.9: py39
[testenv]
deps =
@ -20,12 +28,7 @@ commands =
commands =
python ryu/tests/integrated/run_test.py
[testenv:py27]
commands =
{[testenv]commands}
{[testenv:scenario]commands}
[testenv:py34]
[testenv:py36]
commands =
{[testenv]commands}
{[testenv:scenario]commands}
@ -52,14 +55,15 @@ commands =
[pycodestyle]
exclude = pbr-*,.venv,.tox,.git,doc,dist,tools,vcsversion.py,.pyc,ryu/contrib
# W503: line break occurred before a binary operator
# W503: line break before binary operator
# W504: line break after binary operator
# E116: unexpected indentation (comment)
# E402: module level import not at top of file
# E501: line too long (>79 characters)
# E722: do not use bare except, specify exception instead
# E731: do not assign a lambda expression, use a def
# E741: do not use variables named 'l', 'O', or 'I'
ignore = W503,E116,E402,E501,E722,E731,E741
ignore = W503,W504,E116,E402,E501,E722,E731,E741
[pep8]
exclude = pbr-*,.venv,.tox,.git,doc,dist,tools,vcsversion.py,.pyc,ryu/contrib