mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-05-05 20:36:10 +02:00
Merge branch 'master' into patch-1
This commit is contained in:
commit
f3316fa85a
25
.github/workflows/tests-unit.yml
vendored
Normal file
25
.github/workflows/tests-unit.yml
vendored
Normal 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
11
.readthedocs.yml
Normal 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
15
.renovaterc.json
Normal 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
9
.stickler.yml
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
linters:
|
||||
flake8:
|
||||
python: 3
|
||||
max-line-length: 120
|
||||
pep8:
|
||||
python: 3
|
||||
max-line-length: 120
|
||||
py3k:
|
||||
26
.travis.yml
26
.travis.yml
@ -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
|
||||
@ -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:
|
||||
|
||||
14
README.rst
14
README.rst
@ -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
10
debian/control
vendored
@ -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
2
debian/copyright
vendored
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
6
doc/source/app/bgp_application.rst
Normal file
6
doc/source/app/bgp_application.rst
Normal file
@ -0,0 +1,6 @@
|
||||
**************************************
|
||||
ryu.services.protocols.bgp.application
|
||||
**************************************
|
||||
|
||||
.. automodule:: ryu.services.protocols.bgp.application
|
||||
:members:
|
||||
@ -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
|
||||
|
||||
76
doc/source/library_ovsdb.rst
Normal file
76
doc/source/library_ovsdb.rst
Normal 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:
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -14,5 +14,5 @@
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
version_info = (4, 21)
|
||||
version_info = (4, 34)
|
||||
version = '.'.join(map(str, version_info))
|
||||
|
||||
@ -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']
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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), ... ]
|
||||
"""
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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={})
|
||||
|
||||
@ -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])
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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 \
|
||||
|
||||
BIN
ryu/tests/packet_data/of13/ovs-ofctl-of13-action_ct_clear.packet
Normal file
BIN
ryu/tests/packet_data/of13/ovs-ofctl-of13-action_ct_clear.packet
Normal file
Binary file not shown.
@ -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:
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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)"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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)
|
||||
|
||||
21
ryu/tests/unit/controller/cert.crt
Normal file
21
ryu/tests/unit/controller/cert.crt
Normal 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-----
|
||||
28
ryu/tests/unit/controller/cert.key
Normal file
28
ryu/tests/unit/controller/cert.key
Normal 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-----
|
||||
@ -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))
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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
|
||||
31
ryu/utils.py
31
ryu/utils.py
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
6
setup.py
6
setup.py
@ -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
|
||||
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
22
tox.ini
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user