From c3b484c787f98e6cc7a53a011fd7cacc5607de6d Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Thu, 11 Jan 2018 16:02:39 +0900 Subject: [PATCH 01/93] doc: Usage for ryu/services/protocols/bgp/application.py Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- doc/source/app.rst | 1 + doc/source/app/bgp_application.rst | 6 ++ ryu/services/protocols/bgp/application.py | 120 ++++++++++++++++------ 3 files changed, 98 insertions(+), 29 deletions(-) create mode 100644 doc/source/app/bgp_application.rst diff --git a/doc/source/app.rst b/doc/source/app.rst index 69376dba..eb8bbc20 100644 --- a/doc/source/app.rst +++ b/doc/source/app.rst @@ -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 diff --git a/doc/source/app/bgp_application.rst b/doc/source/app/bgp_application.rst new file mode 100644 index 00000000..47e9fa89 --- /dev/null +++ b/doc/source/app/bgp_application.rst @@ -0,0 +1,6 @@ +************************************** +ryu.services.protocols.bgp.application +************************************** + +.. automodule:: ryu.services.protocols.bgp.application + :members: diff --git a/ryu/services/protocols/bgp/application.py b/ryu/services/protocols/bgp/application.py index ed5961b8..df3e9b95 100644 --- a/ryu/services/protocols/bgp/application.py +++ b/ryu/services/protocols/bgp/application.py @@ -14,7 +14,97 @@ # 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`` + - ``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 + +API Reference +============= """ import logging @@ -140,34 +230,6 @@ 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, From 81cdd4f0d76952c16d6e65e6af8da82702175220 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Thu, 11 Jan 2018 16:02:40 +0900 Subject: [PATCH 02/93] test_rpc: Adopt to msgpack-python>=0.50 msgpack-python version 0.50 or later supports bytearray objects, this patch fixes to adopt to this change. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/tests/unit/lib/test_rpc.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ryu/tests/unit/lib/test_rpc.py b/ryu/tests/unit/lib/test_rpc.py index 2df123ee..4fba5068 100644 --- a/ryu/tests/unit/lib/test_rpc.py +++ b/ryu/tests/unit/lib/test_rpc.py @@ -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 From 37c73db7b1b1c98bd000d4f813423702d73a0c8c Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Mon, 15 Jan 2018 13:51:01 +0900 Subject: [PATCH 03/93] confroller/dpset: Add usage example of instantiation This patch adds the example to explain how to register dpset.DPSet service and how to get DPSet instance from user application in order to call the API of DPSet. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/controller/dpset.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/ryu/controller/dpset.py b/ryu/controller/dpset.py index 8004b2a8..45ead0e0 100644 --- a/ryu/controller/dpset.py +++ b/ryu/controller/dpset.py @@ -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), ... ] """ From e81ec3fb01d74907d77f9f2f6117f346d72a1a8d Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Mon, 15 Jan 2018 12:56:09 +0900 Subject: [PATCH 04/93] ofctl: Enable to get all datapath objects Also, updates the API document of ryu.app.ofctl.api. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/app/ofctl/api.py | 38 ++++++++++++++++++++++++++++++-------- ryu/app/ofctl/event.py | 4 ++-- ryu/app/ofctl/service.py | 16 +++++++--------- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/ryu/app/ofctl/api.py b/ryu/app/ofctl/api.py index 466b3314..fe76b807 100644 --- a/ryu/app/ofctl/api.py +++ b/ryu/app/ofctl/api.py @@ -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,10 +70,17 @@ 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 + + class MyApp(app_manager.RyuApp): + + def _my_handler(self, ev): + # ...(snip)... msg = parser.OFPPortDescStatsRequest(datapath=datapath) - result = api.send_msg(self, msg, + result = ofctl_api.send_msg( + self, msg, reply_cls=parser.OFPPortDescStatsReply, reply_multi=True) """ diff --git a/ryu/app/ofctl/event.py b/ryu/app/ofctl/event.py index 8919452e..dfb0024f 100644 --- a/ryu/app/ofctl/event.py +++ b/ryu/app/ofctl/event.py @@ -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 diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py index 2a2e97d1..ce604958 100644 --- a/ryu/app/ofctl/service.py +++ b/ryu/app/ofctl/service.py @@ -99,15 +99,13 @@ class OfctlService(app_manager.RyuApp): @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): From 80312a4d64112dc2e8297b4017e24c95bd2bc18f Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 23 Jan 2018 09:41:33 +0900 Subject: [PATCH 05/93] BGPSpeaker: Enable to notify adj-RIB-in changed This patch introduces a new argument "adj_rib_in_change_handler" into BGPSpeaker and enables to notify adj-RIB-in changed to watchers. Also this patch enables to "bgp.application.RyuBGPSpeaker" to notify a new event EventAdjRibInChanged to other Ryu applications. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/services/protocols/bgp/application.py | 35 +++++++++++++++++++++++ ryu/services/protocols/bgp/bgpspeaker.py | 24 ++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/ryu/services/protocols/bgp/application.py b/ryu/services/protocols/bgp/application.py index df3e9b95..31cfb5f0 100644 --- a/ryu/services/protocols/bgp/application.py +++ b/ryu/services/protocols/bgp/application.py @@ -62,6 +62,7 @@ Integration with Other Applications following events to other Ryu applications. - ``EventBestPathChanged`` + - ``EventAdjRibInChanged`` - ``EventPeerDown`` - ``EventPeerUp`` @@ -191,6 +192,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. @@ -233,6 +261,7 @@ class RyuBGPSpeaker(RyuApp): """ _EVENTS = [ EventBestPathChanged, + EventAdjRibInChanged, EventPeerDown, EventPeerUp, ] @@ -299,6 +328,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( @@ -330,6 +361,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) diff --git a/ryu/services/protocols/bgp/bgpspeaker.py b/ryu/services/protocols/bgp/bgpspeaker.py index 14e5eed9..5131c9ce 100644 --- a/ryu/services/protocols/bgp/bgpspeaker.py +++ b/ryu/services/protocols/bgp/bgpspeaker.py @@ -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 @@ -226,6 +227,7 @@ class BGPSpeaker(object): 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, @@ -263,6 +265,12 @@ class BGPSpeaker(object): 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. @@ -315,6 +323,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 +360,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 +376,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: From 7d0b080e734d10ef54d5e93726aac28da3025f5c Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 23 Jan 2018 09:41:34 +0900 Subject: [PATCH 06/93] BGPSpeaker: Move docstring from __init__ to class By the default, Sphinx does not include __init__() method for the "autoclass" directive, and currently the description for the arguments of BGPSpeaker is not generated. This patch moves the docstring of __init__() to the class's docstring and enables to generate the docs for the arguments of __init__(). Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/services/protocols/bgp/bgpspeaker.py | 139 +++++++++++------------ 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/ryu/services/protocols/bgp/bgpspeaker.py b/ryu/services/protocols/bgp/bgpspeaker.py index 5131c9ce..46cbcaf1 100644 --- a/ryu/services/protocols/bgp/bgpspeaker.py +++ b/ryu/services/protocols/bgp/bgpspeaker.py @@ -221,6 +221,75 @@ 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, @@ -236,76 +305,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. - - ``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. - """ - super(BGPSpeaker, self).__init__() settings = { From fa172559c586beeaa5d3ef8a5a1b94405faa50da Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 23 Jan 2018 09:41:35 +0900 Subject: [PATCH 07/93] bgp/application: Add note for BGPSpeaker API reference Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/services/protocols/bgp/application.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ryu/services/protocols/bgp/application.py b/ryu/services/protocols/bgp/application.py index 31cfb5f0..b4ae49cf 100644 --- a/ryu/services/protocols/bgp/application.py +++ b/ryu/services/protocols/bgp/application.py @@ -104,6 +104,11 @@ 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 ============= """ From fb224e23b9b79bbebc1c500b4f51cb83bb5bd453 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 1 Feb 2018 20:56:39 +0900 Subject: [PATCH 08/93] Ryu 4.22 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index b3dccc8a..578d7e0a 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 21) +version_info = (4, 22) version = '.'.join(map(str, version_info)) From bd384997ac216da371a642ec96e20fd348a757c5 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Mon, 5 Feb 2018 09:46:44 +0900 Subject: [PATCH 09/93] lib/ovs: Fix a typo of "--may-exist" option Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/ovs/vsctl.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py index 2391c903..b18b5ef1 100644 --- a/ryu/lib/ovs/vsctl.py +++ b/ryu/lib/ovs/vsctl.py @@ -1563,7 +1563,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 +1579,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] From 09d2811569c891837db6add51cf3cbe1e86580b5 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Mon, 5 Feb 2018 09:46:45 +0900 Subject: [PATCH 10/93] doc: Document for ryu.lib.ovs Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- doc/source/library.rst | 1 + doc/source/library_ovsdb.rst | 76 ++++++++++++++++++++ ryu/lib/ovs/bridge.py | 134 ++++++++++++++++++++++++++++++++++- ryu/lib/ovs/vsctl.py | 57 ++++++++++++++- 4 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 doc/source/library_ovsdb.rst diff --git a/doc/source/library.rst b/doc/source/library.rst index ff280415..cdaed768 100644 --- a/doc/source/library.rst +++ b/doc/source/library.rst @@ -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 diff --git a/doc/source/library_ovsdb.rst b/doc/source/library_ovsdb.rst new file mode 100644 index 00000000..df7d1708 --- /dev/null +++ b/doc/source/library_ovsdb.rst @@ -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=[]) + 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: diff --git a/ryu/lib/ovs/bridge.py b/ryu/lib/ovs/bridge.py index e48052fb..9753fa29 100644 --- a/ryu/lib/ovs/bridge.py +++ b/ryu/lib/ovs/bridge.py @@ -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,37 @@ 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 + """ command = ovs_vsctl.VSCtlCommand('get-controller', [self.br_name]) self.run_command([command]) return command.result[0] def set_controller(self, controllers): + """ + Sets the OpenFlow controller address. + + This method is corresponding to the following ovs-vsctl command:: + + $ ovs-vsctl set-controller ... + """ 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 + """ command = ovs_vsctl.VSCtlCommand('del-controller', [self.br_name]) self.run_command([command]) @@ -245,30 +302,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 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 + """ 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 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 + """ command = ovs_vsctl.VSCtlCommand('list-ports', (self.br_name, )) self.run_command([command]) return command.result @@ -297,6 +396,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 +423,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 + """ command = ovs_vsctl.VSCtlCommand('del-port', (self.br_name, port_name)) self.run_command([command]) @@ -396,6 +522,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 +538,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]) diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py index b18b5ef1..f3355a1c 100644 --- a/ryu/lib/ovs/vsctl.py +++ b/ryu/lib/ovs/vsctl.py @@ -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). @@ -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: From 8a48b62c90745e8112bb3f7277e8ac46dabb3e4e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 2 Mar 2018 10:29:20 +0900 Subject: [PATCH 11/93] Ryu 4.23 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index 578d7e0a..c9e5a025 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 22) +version_info = (4, 23) version = '.'.join(map(str, version_info)) From 0841f3f253a4a6479dabfcd2bbd29e92d2fa7896 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Thu, 1 Mar 2018 14:22:32 +0900 Subject: [PATCH 12/93] doc: Fix unexpected indent in ofctl.api doc Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/app/ofctl/api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ryu/app/ofctl/api.py b/ryu/app/ofctl/api.py index fe76b807..1149e06d 100644 --- a/ryu/app/ofctl/api.py +++ b/ryu/app/ofctl/api.py @@ -78,11 +78,11 @@ def send_msg(app, msg, reply_cls=None, reply_multi=False): def _my_handler(self, ev): # ...(snip)... - msg = parser.OFPPortDescStatsRequest(datapath=datapath) + msg = parser.OFPPortDescStatsRequest(datapath=datapath) result = ofctl_api.send_msg( self, msg, - reply_cls=parser.OFPPortDescStatsReply, - reply_multi=True) + reply_cls=parser.OFPPortDescStatsReply, + reply_multi=True) """ return app.send_request(event.SendMsgRequest(msg=msg, reply_cls=reply_cls, From 684b665290c91d9ac1b1f6f9865506c6a655b1aa Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Thu, 8 Mar 2018 15:40:23 +0900 Subject: [PATCH 13/93] nicira_ext: Support Network Service Header match Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/packet/ether_types.py | 1 + ryu/ofproto/nicira_ext.py | 38 +++++++++++++++++++++++++++++++++++ ryu/ofproto/ofproto_common.py | 1 + ryu/ofproto/oxm_fields.py | 4 ++++ 4 files changed, 44 insertions(+) diff --git a/ryu/lib/packet/ether_types.py b/ryu/lib/packet/ether_types.py index e8287d3b..ff2ba67b 100644 --- a/ryu/lib/packet/ether_types.py +++ b/ryu/lib/packet/ether_types.py @@ -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 diff --git a/ryu/ofproto/nicira_ext.py b/ryu/ofproto/nicira_ext.py index 9e0f8873..94f38fc1 100644 --- a/ryu/ofproto/nicira_ext.py +++ b/ryu/ofproto/nicira_ext.py @@ -590,6 +590,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 Integer 32bit Context fields in NSH Context Header. + 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 Integer 32bit Packet register. is register number 0-15. xxreg Integer 128bit Packet extended-extended register. @@ -684,6 +707,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" + 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), diff --git a/ryu/ofproto/ofproto_common.py b/ryu/ofproto/ofproto_common.py index 4f0d9956..ffdf1a4a 100644 --- a/ryu/ofproto/ofproto_common.py +++ b/ryu/ofproto/ofproto_common.py @@ -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 diff --git a/ryu/ofproto/oxm_fields.py b/ryu/ofproto/oxm_fields.py index d2bea495..f978f5b1 100644 --- a/ryu/ofproto/oxm_fields.py +++ b/ryu/ofproto/oxm_fields.py @@ -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) From a0f90115cc8306435d219923441ea5fda38c9a92 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Thu, 8 Mar 2018 15:40:24 +0900 Subject: [PATCH 14/93] nicira_ext: Support DEC_NSH_TTL action Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- doc/source/nicira_ext_ref.rst | 1 + ryu/ofproto/nicira_ext.py | 1 + ryu/ofproto/nx_actions.py | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/doc/source/nicira_ext_ref.rst b/doc/source/nicira_ext_ref.rst index 739349c4..7ca1b0c7 100644 --- a/doc/source/nicira_ext_ref.rst +++ b/doc/source/nicira_ext_ref.rst @@ -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 diff --git a/ryu/ofproto/nicira_ext.py b/ryu/ofproto/nicira_ext.py index 94f38fc1..4a06b647 100644 --- a/ryu/ofproto/nicira_ext.py +++ b/ryu/ofproto/nicira_ext.py @@ -62,6 +62,7 @@ NXAST_NAT = 36 NXAST_CONTROLLER2 = 37 NXAST_SAMPLE2 = 38 NXAST_OUTPUT_TRUNC = 39 +NXAST_DEC_NSH_TTL = 48 NX_ACTION_RESUBMIT_PACK_STR = '!HHIHHB3x' NX_ACTION_RESUBMIT_SIZE = 16 diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py index 89210070..18dc9210 100644 --- a/ryu/ofproto/nx_actions.py +++ b/ryu/ofproto/nx_actions.py @@ -2984,6 +2984,41 @@ def generate(ofp_name, ofpp_name): self.max_len) 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) @@ -3032,6 +3067,7 @@ def generate(ofp_name, ofpp_name): 'NXFlowSpecMatch', 'NXFlowSpecLoad', 'NXFlowSpecOutput', + 'NXActionDecNshTtl', ] vars = locals() for name in classes: From e6773539b546576c13f7397769d2001c46bbfdaa Mon Sep 17 00:00:00 2001 From: Thomas Bechtold Date: Mon, 5 Mar 2018 18:41:10 +0100 Subject: [PATCH 15/93] Switch to msgpack in pip-requires msgpack-python got renamed to msgpack[1] so use the new name. [1] https://pypi.python.org/pypi/msgpack/0.5.1 Signed-off-by: Thomas Bechtold Acked-By: Iwase Yusuke Signed-off-by: FUJITA Tomonori --- tools/pip-requires | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pip-requires b/tools/pip-requires index ef475c0a..b2b79b89 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -2,7 +2,7 @@ # 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) +msgpack>=0.3.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=1.15.0 ovs>=2.6.0 # OVSDB From a27c56a0542388f3d2390a9f013ba21b99c854b0 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 23 Mar 2018 10:24:35 +0900 Subject: [PATCH 16/93] utils: Remove "parse_requirements" function This patch removes unused function "parse_requirements" in order to avoid using "pip" as a Python library. Note: Officially "from pip import req as pip_req" is not supported usage of "pip". Reported-by: Katsaounis Molyvas Stamatios Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/utils.py | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/ryu/utils.py b/ryu/utils.py index 8bfdf7da..ca14c12c 100644 --- a/ryu/utils.py +++ b/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 From fe06d87f65aabd80724a9fed12c695d192eeb999 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 23 Mar 2018 10:24:36 +0900 Subject: [PATCH 17/93] test_requirements: Avoid using pip as library Because importing "pip" in Python scripts is not supported usage of "pip", this patch fixes to use "pkg_resources" + "urllib" instead. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/tests/unit/test_requirements.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ryu/tests/unit/test_requirements.py b/ryu/tests/unit/test_requirements.py index 9f50a518..c842a0f0 100644 --- a/ryu/tests/unit/test_requirements.py +++ b/ryu/tests/unit/test_requirements.py @@ -19,8 +19,6 @@ 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_ @@ -28,7 +26,7 @@ from nose.tools import ok_ LOG = logging.getLogger(__name__) -MOD_DIR = os.path.dirname(sys.modules[__name__].__file__) +MOD_DIR = os.path.dirname('file://' + sys.modules[__name__].__file__) _RYU_REQUIREMENTS_FILES = [ '../../../tools/pip-requires', '../../../tools/optional-requires', @@ -51,9 +49,10 @@ 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) + response = urllib.request.urlopen(f) + contents = response.read().decode('utf-8') + for r in pkg_resources.parse_requirements(contents): + requirements[r.name] = str(r) return requirements @@ -82,5 +81,5 @@ class TestRequirements(unittest.TestCase): except pkg_resources.VersionConflict as e: LOG.exception( 'Some requirements of Ryu are conflicting with that of ' - 'OpenStack project: %s' % OPENSTACK_REQUIREMENTS_REPO) + 'OpenStack project: %s', OPENSTACK_REQUIREMENTS_REPO) raise e From 976914f5e651ace55ef4e7f847381b37a9c386c4 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 6 Mar 2018 15:52:19 +0900 Subject: [PATCH 18/93] controller: Improve pylint result Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/controller/controller.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index 84848917..c0e58659 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -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_RDWR +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 @@ -300,7 +302,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 +314,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 +337,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)] @@ -424,7 +428,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): From 7a40d5c2f305d8200566d735619c7605ab778080 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 6 Mar 2018 15:52:20 +0900 Subject: [PATCH 19/93] controller: Option to close socket after sending Message Currently, Ryu does not provide the way to close a socket connecting to a switch after sending all enqueued messages, but provides only the way to close the socket immediately regardless of enqueued messages. This patch adds a new option "close_socket" into "Datapath.send_msg()" method and this option enables to close the socket after sending the given message. This patch is convenient to close the socket after sending OFPT_ERROR message to the switch. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/controller/controller.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index c0e58659..f46cf009 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -362,9 +362,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) @@ -387,11 +389,11 @@ class Datapath(ofproto_protocol.ProtocolDesc): # Finally, ensure the _recv_loop terminates. self.close() - 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() @@ -406,13 +408,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: From afbc80352cd2ce69291939bacdf5bd5ea6d39eb5 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 6 Mar 2018 15:52:21 +0900 Subject: [PATCH 20/93] controller: Wait for switch to disconnect connection If a sender closes a socket immediately after sending some data, a receiver can fail to receive full data from the sender. This patch fixes to shutdown a socket with "SHUT_WR" (disallows further sends only) and enables "Datapath" to wait for a switch to disconnect the connection. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/controller/controller.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index f46cf009..62135339 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -27,7 +27,7 @@ import logging import random from socket import IPPROTO_TCP from socket import TCP_NODELAY -from socket import SHUT_RDWR +from socket import SHUT_WR from socket import timeout as SocketTimeout import ssl @@ -196,12 +196,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 @@ -279,14 +277,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 @@ -386,8 +394,8 @@ 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, close_socket=False): msg_enqueued = False From 3003d475d268efbff0fa2df56104968e71761ca8 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 6 Mar 2018 15:52:22 +0900 Subject: [PATCH 21/93] ofp_handler: Close socket when HELLO failed With this patch, when failed to negotiate the OpenFlow version with a switch, Ryu will close the socket connecting to the switch after sending a OFPT_ERROR message. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/controller/ofp_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/controller/ofp_handler.py b/ryu/controller/ofp_handler.py index 4f439c2e..6ab02fe8 100644 --- a/ryu/controller/ofp_handler.py +++ b/ryu/controller/ofp_handler.py @@ -65,7 +65,7 @@ class OFPHandler(ryu.base.app_manager.RyuApp): 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) + datapath.send_msg(error_msg, close_socket=True) @set_ev_handler(ofp_event.EventOFPHello, HANDSHAKE_DISPATCHER) def hello_handler(self, ev): From 4e10ba44381ca5fa095b5cfc69e7c6fc407642a8 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Tue, 6 Mar 2018 15:52:23 +0900 Subject: [PATCH 22/93] ofproto: Encode data field on OFPErrorMsg Currently, when Ryu failed to negotiate the OpenFlow version with a switch, Ryu will send the OFPT_ERROR message with an error reason on its data field. But on Python 3, error reason string is a str type value and required to be encoded into a bytes type value, otherwise causes an exception when sending the message. This patch fixes to encode the given str value into a bytes type value in OFPErrorMsg.__init__() and solves this problem. Signed-off-by: William Fisher Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/controller/ofp_handler.py | 11 ++++++----- ryu/ofproto/ofproto_v1_0_parser.py | 2 ++ ryu/ofproto/ofproto_v1_2_parser.py | 2 ++ ryu/ofproto/ofproto_v1_3_parser.py | 2 ++ ryu/ofproto/ofproto_v1_4_parser.py | 2 ++ ryu/ofproto/ofproto_v1_5_parser.py | 2 ++ 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ryu/controller/ofp_handler.py b/ryu/controller/ofp_handler.py index 6ab02fe8..5c4d46de 100644 --- a/ryu/controller/ofp_handler.py +++ b/ryu/controller/ofp_handler.py @@ -60,11 +60,12 @@ 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 + 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) diff --git a/ryu/ofproto/ofproto_v1_0_parser.py b/ryu/ofproto/ofproto_v1_0_parser.py index bfc55512..a288964a 100644 --- a/ryu/ofproto/ofproto_v1_0_parser.py +++ b/ryu/ofproto/ofproto_v1_0_parser.py @@ -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 diff --git a/ryu/ofproto/ofproto_v1_2_parser.py b/ryu/ofproto/ofproto_v1_2_parser.py index 9b4dda4b..244126c3 100644 --- a/ryu/ofproto/ofproto_v1_2_parser.py +++ b/ryu/ofproto/ofproto_v1_2_parser.py @@ -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) diff --git a/ryu/ofproto/ofproto_v1_3_parser.py b/ryu/ofproto/ofproto_v1_3_parser.py index 7730aa12..0324c82b 100644 --- a/ryu/ofproto/ofproto_v1_3_parser.py +++ b/ryu/ofproto/ofproto_v1_3_parser.py @@ -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) diff --git a/ryu/ofproto/ofproto_v1_4_parser.py b/ryu/ofproto/ofproto_v1_4_parser.py index fca35f57..470e2013 100644 --- a/ryu/ofproto/ofproto_v1_4_parser.py +++ b/ryu/ofproto/ofproto_v1_4_parser.py @@ -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) diff --git a/ryu/ofproto/ofproto_v1_5_parser.py b/ryu/ofproto/ofproto_v1_5_parser.py index 03946622..c19a7e8d 100644 --- a/ryu/ofproto/ofproto_v1_5_parser.py +++ b/ryu/ofproto/ofproto_v1_5_parser.py @@ -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) From b8ebdbe961ec3387c3be96a01dbef29ec3f064ab Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 28 Mar 2018 16:48:34 +0900 Subject: [PATCH 23/93] ofproto: add Nicira extension ct_clear action Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/lib/ofctl_string.py | 4 ++ ryu/ofproto/nicira_ext.py | 1 + ryu/ofproto/nx_actions.py | 38 ++++++++++++ .../ovs-ofctl-of13-action_ct_clear.packet | Bin 0 -> 96 bytes ryu/tests/packet_data_generator3/gen.py | 7 +++ ...ovs-ofctl-of13-action_ct_clear.packet.json | 55 ++++++++++++++++++ 6 files changed, 105 insertions(+) create mode 100644 ryu/tests/packet_data/of13/ovs-ofctl-of13-action_ct_clear.packet create mode 100644 ryu/tests/unit/ofproto/json/of13/ovs-ofctl-of13-action_ct_clear.packet.json diff --git a/ryu/lib/ofctl_string.py b/ryu/lib/ofctl_string.py index 06a91af2..30394c65 100644 --- a/ryu/lib/ofctl_string.py +++ b/ryu/lib/ofctl_string.py @@ -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={}) diff --git a/ryu/ofproto/nicira_ext.py b/ryu/ofproto/nicira_ext.py index 4a06b647..73297cfb 100644 --- a/ryu/ofproto/nicira_ext.py +++ b/ryu/ofproto/nicira_ext.py @@ -62,6 +62,7 @@ NXAST_NAT = 36 NXAST_CONTROLLER2 = 37 NXAST_SAMPLE2 = 38 NXAST_OUTPUT_TRUNC = 39 +NXAST_CT_CLEAR = 43 NXAST_DEC_NSH_TTL = 48 NX_ACTION_RESUBMIT_PACK_STR = '!HHIHHB3x' diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py index 18dc9210..ae5c48f4 100644 --- a/ryu/ofproto/nx_actions.py +++ b/ryu/ofproto/nx_actions.py @@ -2766,6 +2766,43 @@ def generate(ofp_name, ofpp_name): a.serialize(data, len(data)) return data + 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): """ Network address translation action @@ -3061,6 +3098,7 @@ def generate(ofp_name, ofpp_name): 'NXActionBundle', 'NXActionBundleLoad', 'NXActionCT', + 'NXActionCTClear', 'NXActionNAT', 'NXActionOutputTrunc', '_NXFlowSpec', # exported for testing diff --git a/ryu/tests/packet_data/of13/ovs-ofctl-of13-action_ct_clear.packet b/ryu/tests/packet_data/of13/ovs-ofctl-of13-action_ct_clear.packet new file mode 100644 index 0000000000000000000000000000000000000000..13bc390177cca46df2f76f0d5a0b54152620a94e GIT binary patch literal 96 zcmZSKV@P1Y0+_*K4GjO009c5TL9Bs+i;07Qf$=hsU{HW!76u8B{Qv(90t^hw3JlsH H9s>gaa8(gW literal 0 HcmV?d00001 diff --git a/ryu/tests/packet_data_generator3/gen.py b/ryu/tests/packet_data_generator3/gen.py index 0216dc42..dca45cf9 100644 --- a/ryu/tests/packet_data_generator3/gen.py +++ b/ryu/tests/packet_data_generator3/gen.py @@ -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', diff --git a/ryu/tests/unit/ofproto/json/of13/ovs-ofctl-of13-action_ct_clear.packet.json b/ryu/tests/unit/ofproto/json/of13/ovs-ofctl-of13-action_ct_clear.packet.json new file mode 100644 index 00000000..32b88b72 --- /dev/null +++ b/ryu/tests/unit/ofproto/json/of13/ovs-ofctl-of13-action_ct_clear.packet.json @@ -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 + } +} From 1c008060fa3dab51c3a59c1485a7529b13cf0dd1 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 1 Apr 2018 15:15:49 +0900 Subject: [PATCH 24/93] Ryu 4.24 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index c9e5a025..36bf4254 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 23) +version_info = (4, 24) version = '.'.join(map(str, version_info)) From cda5bc7825d9c7fe039d6dd0b3159ba4d4403ae9 Mon Sep 17 00:00:00 2001 From: Joe Mader Date: Sun, 13 May 2018 09:37:47 -0600 Subject: [PATCH 25/93] allow versions of eventlet > 0.21.0 --- tools/pip-requires | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/pip-requires b/tools/pip-requires index b2b79b89..7b70715a 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,7 +1,7 @@ -# 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 +eventlet!=0.18.3,>=0.18.2,!=0.20.1,!=0.21.0 msgpack>=0.3.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=1.15.0 From c29c9019ac8ab862bbc0caad7d49220f27ed0cf0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 1 Jun 2018 20:43:17 +0900 Subject: [PATCH 26/93] Ryu 4.25 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index 36bf4254..8cf62018 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 24) +version_info = (4, 25) version = '.'.join(map(str, version_info)) From 99fc573a9c169ca5561e7e763c5083a57b3d9729 Mon Sep 17 00:00:00 2001 From: Marcin Chron Date: Thu, 17 May 2018 23:32:17 +0200 Subject: [PATCH 27/93] lldp: fixed SystemCapabilities TLV This patch removes 'Subtype' byte from SystemCapabilities TLV. There was an inconsistency in offical IEEE document which was corrected in 802.1AB-2009/Cor 1-2013. Signed-off-by: Marcin Chron Signed-off-by: FUJITA Tomonori --- ryu/lib/packet/lldp.py | 15 ++++++--------- ryu/tests/unit/packet/test_lldp.py | 4 +--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/ryu/lib/packet/lldp.py b/ryu/lib/packet/lldp.py index 914f07c1..a48884d7 100644 --- a/ryu/lib/packet/lldp.py +++ b/ryu/lib/packet/lldp.py @@ -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) diff --git a/ryu/tests/unit/packet/test_lldp.py b/ryu/tests/unit/packet/test_lldp.py index d8d261c2..a5c96bda 100644 --- a/ryu/tests/unit/packet/test_lldp.py +++ b/ryu/tests/unit/packet/test_lldp.py @@ -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, From 482aabcb1ea5c4c973b1cecf65721b3039f481df Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Thu, 14 Jun 2018 12:29:41 +0900 Subject: [PATCH 28/93] lldp: Remove remaining SystemCapabilities.subtype from tests Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/tests/unit/packet/test_lldp.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ryu/tests/unit/packet/test_lldp.py b/ryu/tests/unit/packet/test_lldp.py index a5c96bda..35c4f58e 100644 --- a/ryu/tests/unit/packet/test_lldp.py +++ b/ryu/tests/unit/packet/test_lldp.py @@ -320,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( @@ -358,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( @@ -432,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} @@ -513,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( From a6bda030d376137157840862fe6087f8e20e943f Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 20 Jun 2018 11:08:56 +0900 Subject: [PATCH 29/93] pip: Blacklist eventlet 0.23.0 This is to sync with OpenStack requirements. Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- tools/pip-requires | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pip-requires b/tools/pip-requires index 7b70715a..7a131ddf 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,7 +1,7 @@ # 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 +eventlet!=0.18.3,>=0.18.2,!=0.20.1,!=0.21.0,!=0.23.0 msgpack>=0.3.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=1.15.0 From db7338b8dbc7e92415d0674c0345b50550027b40 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Wed, 13 Jun 2018 15:57:29 +0900 Subject: [PATCH 30/93] BGPSpeaker: Advertise local routes to RR clients The current implementation misses the mandatory attributes when sending locally generated routes to its Route Reflector (RR) clients, then the clients will reject the received routes. This patch fixes to add or update attributes to for sending locally generated routes its RR clients. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/services/protocols/bgp/peer.py | 47 +++++++++++++----------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 70b486c0..2a0e2a9f 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -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 From 56aff9adf393bf02058e8e0a571dd3054e98ac0a Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Wed, 13 Jun 2018 15:57:30 +0900 Subject: [PATCH 31/93] pycodestyle: Ignore W504 Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- tox.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 758d1661..c1759acb 100644 --- a/tox.ini +++ b/tox.ini @@ -52,14 +52,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 From b1ec9ed457a30663f775cb2f73d008b8649519f8 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Wed, 13 Jun 2018 15:57:31 +0900 Subject: [PATCH 32/93] BGPSpeaker: Fix BGP state string conversion The constants BGP_FSM_* are str type values and not callable. Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/services/protocols/bgp/peer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 2a0e2a9f..2c6e3898 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -2000,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. From 4bc29b2c5f7e3eca6245da658743738bc400ecb9 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 13 Jun 2018 12:02:15 +0900 Subject: [PATCH 33/93] Fix pycodestyle W605 warnings W605 invalid escape sequence, which was recently added in pycodestyle, would be a syntax error in future python3 versions. Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/app/rest_qos.py | 6 +- ryu/lib/ofctl_string.py | 4 +- ryu/lib/ovs/vsctl.py | 4 +- ryu/lib/packet/bmp.py | 16 ++--- ryu/lib/packet/icmpv6.py | 6 +- ryu/lib/packet/igmp.py | 2 +- ryu/lib/packet/ipv6.py | 4 +- ryu/lib/stringify.py | 2 +- ryu/ofproto/nicira_ext.py | 2 +- ryu/ofproto/nx_actions.py | 64 +++++++++---------- ryu/tests/integrated/test_vrrp_linux_multi.py | 2 +- ryu/tests/integrated/test_vrrp_multi.py | 2 +- ryu/tests/packet_data_generator3/gen.py | 2 +- 13 files changed, 58 insertions(+), 58 deletions(-) diff --git a/ryu/app/rest_qos.py b/ryu/app/rest_qos.py index c5bac29a..ee3d45f4 100644 --- a/ryu/app/rest_qos.py +++ b/ryu/app/rest_qos.py @@ -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} diff --git a/ryu/lib/ofctl_string.py b/ryu/lib/ofctl_string.py index 30394c65..fe0eeaea 100644 --- a/ryu/lib/ofctl_string.py +++ b/ryu/lib/ofctl_string.py @@ -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))) diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py index f3355a1c..53ee7f42 100644 --- a/ryu/lib/ovs/vsctl.py +++ b/ryu/lib/ovs/vsctl.py @@ -66,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) diff --git a/ryu/lib/packet/bmp.py b/ryu/lib/packet/bmp.py index bc49c577..0b4c3b84 100644 --- a/ryu/lib/packet/bmp.py +++ b/ryu/lib/packet/bmp.py @@ -69,7 +69,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 +141,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. @@ -250,7 +250,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 @@ -308,7 +308,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 @@ -424,7 +424,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 @@ -498,7 +498,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 @@ -605,7 +605,7 @@ class BMPPeerUpNotification(BMPPeerMessage): @BMPMessage.register_type(BMP_MSG_INITIATION) class BMPInitiation(BMPMessage): - """BMP Initiation Message + r"""BMP Initiation Message ========================== =============================================== Attribute Description @@ -669,7 +669,7 @@ class BMPInitiation(BMPMessage): @BMPMessage.register_type(BMP_MSG_TERMINATION) class BMPTermination(BMPMessage): - """BMP Termination Message + r"""BMP Termination Message ========================== =============================================== Attribute Description diff --git a/ryu/lib/packet/icmpv6.py b/ryu/lib/packet/icmpv6.py index 00b883bf..a391c087 100644 --- a/ryu/lib/packet/icmpv6.py +++ b/ryu/lib/packet/icmpv6.py @@ -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. @@ -884,7 +884,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) diff --git a/ryu/lib/packet/igmp.py b/ryu/lib/packet/igmp.py index 8935da3b..d4c9552c 100644 --- a/ryu/lib/packet/igmp.py +++ b/ryu/lib/packet/igmp.py @@ -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. diff --git a/ryu/lib/packet/ipv6.py b/ryu/lib/packet/ipv6.py index 007dc564..6ceaced3 100644 --- a/ryu/lib/packet/ipv6.py +++ b/ryu/lib/packet/ipv6.py @@ -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. diff --git a/ryu/lib/stringify.py b/ryu/lib/stringify.py index 94ffbbcb..e178408b 100644 --- a/ryu/lib/stringify.py +++ b/ryu/lib/stringify.py @@ -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. diff --git a/ryu/ofproto/nicira_ext.py b/ryu/ofproto/nicira_ext.py index 73297cfb..9ac673a3 100644 --- a/ryu/ofproto/nicira_ext.py +++ b/ryu/ofproto/nicira_ext.py @@ -298,7 +298,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. diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py index ae5c48f4..5fe0d545 100644 --- a/ryu/ofproto/nx_actions.py +++ b/ryu/ofproto/nx_actions.py @@ -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. @@ -600,7 +600,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 @@ -648,7 +648,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 +737,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 +786,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 +840,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 +914,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 +996,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 +1260,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 +1325,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 +1571,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 +1682,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 +1717,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 +1752,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 +1851,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 +1906,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 +2000,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 +2032,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 +2064,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 +2137,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 +2218,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 +2279,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 +2342,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 +2528,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 +2581,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 +2642,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. @@ -2804,7 +2804,7 @@ def generate(ofp_name, ofpp_name): return data class NXActionNAT(NXAction): - """ + r""" Network address translation action This action sends the packet through the connection tracker. @@ -2967,7 +2967,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. diff --git a/ryu/tests/integrated/test_vrrp_linux_multi.py b/ryu/tests/integrated/test_vrrp_linux_multi.py index dca70c47..ac5c3252 100644 --- a/ryu/tests/integrated/test_vrrp_linux_multi.py +++ b/ryu/tests/integrated/test_vrrp_linux_multi.py @@ -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 \ diff --git a/ryu/tests/integrated/test_vrrp_multi.py b/ryu/tests/integrated/test_vrrp_multi.py index 6aee6395..a26d949a 100644 --- a/ryu/tests/integrated/test_vrrp_multi.py +++ b/ryu/tests/integrated/test_vrrp_multi.py @@ -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 \ diff --git a/ryu/tests/packet_data_generator3/gen.py b/ryu/tests/packet_data_generator3/gen.py index dca45cf9..7f2fbeef 100644 --- a/ryu/tests/packet_data_generator3/gen.py +++ b/ryu/tests/packet_data_generator3/gen.py @@ -319,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: From 704dcc786aa9f975a9d486d9a1699fd7995ecd4b Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 13 Jun 2018 12:02:16 +0900 Subject: [PATCH 34/93] nx_actions: Fix NXActionSetTunnel docstring set_tunnel and set_field:xxx->tun_id are different actions. Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/ofproto/nx_actions.py | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py index 5fe0d545..7f543471 100644 --- a/ryu/ofproto/nx_actions.py +++ b/ryu/ofproto/nx_actions.py @@ -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 ================ ====================================================== @@ -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 ================ ====================================================== From b9909d06862454d4907c29b0688788ab80406f9b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 1 Jul 2018 20:10:13 +0900 Subject: [PATCH 35/93] Ryu 4.26 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index 8cf62018..b4625d3b 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 25) +version_info = (4, 26) version = '.'.join(map(str, version_info)) From 2c6a053f8d2fa48a59a1c43abce0a4981548a541 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 11 Jul 2018 13:51:48 +0900 Subject: [PATCH 36/93] gui_topology: Avoid wildcard URL matching GUIServerController eats up the entire URL space and sometimes causes problems. See the following thread in ryu-devel for example: https://sourceforge.net/p/ryu/mailman/message/36312411/ Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/app/gui_topology/gui_topology.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/app/gui_topology/gui_topology.py b/ryu/app/gui_topology/gui_topology.py index ed4857a5..cbac4d8f 100644 --- a/ryu/app/gui_topology/gui_topology.py +++ b/ryu/app/gui_topology/gui_topology.py @@ -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'] From d96e6a60ab15abffe1ddd63a6dd0e36de0b41bf3 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Thu, 12 Jul 2018 12:29:35 +0900 Subject: [PATCH 37/93] switch.tester: Fix name shadowing tester.py imported all the classes from the packet library at the top level namespace. This commit adds CLSNAME_ALIASES dict so that those classes with the same names can be imported as different names. This fixes an issue reported by ted.nozaki in ryu-devel: https://sourceforge.net/p/ryu/mailman/message/36312622/ Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- .../action/25_SET_FIELD/29_ICMPV6_TYPE.json | 16 +++++----- .../action/25_SET_FIELD/30_ICMPV6_CODE.json | 16 +++++----- .../switch/of13/match/29_ICMPV6_TYPE.json | 32 +++++++++---------- .../switch/of13/match/30_ICMPV6_CODE.json | 32 +++++++++---------- .../action/25_SET_FIELD/29_ICMPV6_TYPE.json | 16 +++++----- .../action/25_SET_FIELD/30_ICMPV6_CODE.json | 16 +++++----- .../switch/of14/match/29_ICMPV6_TYPE.json | 32 +++++++++---------- .../switch/of14/match/30_ICMPV6_CODE.json | 32 +++++++++---------- ryu/tests/switch/tester.py | 20 +++++++++++- 9 files changed, 115 insertions(+), 97 deletions(-) diff --git a/ryu/tests/switch/of13/action/25_SET_FIELD/29_ICMPV6_TYPE.json b/ryu/tests/switch/of13/action/25_SET_FIELD/29_ICMPV6_TYPE.json index 56240928..5c55502f 100644 --- a/ryu/tests/switch/of13/action/25_SET_FIELD/29_ICMPV6_TYPE.json +++ b/ryu/tests/switch/of13/action/25_SET_FIELD/29_ICMPV6_TYPE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of13/action/25_SET_FIELD/30_ICMPV6_CODE.json b/ryu/tests/switch/of13/action/25_SET_FIELD/30_ICMPV6_CODE.json index 9a8570aa..972455ec 100644 --- a/ryu/tests/switch/of13/action/25_SET_FIELD/30_ICMPV6_CODE.json +++ b/ryu/tests/switch/of13/action/25_SET_FIELD/30_ICMPV6_CODE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of13/match/29_ICMPV6_TYPE.json b/ryu/tests/switch/of13/match/29_ICMPV6_TYPE.json index db0dd123..182ee593 100644 --- a/ryu/tests/switch/of13/match/29_ICMPV6_TYPE.json +++ b/ryu/tests/switch/of13/match/29_ICMPV6_TYPE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of13/match/30_ICMPV6_CODE.json b/ryu/tests/switch/of13/match/30_ICMPV6_CODE.json index 739678d4..aee2edf7 100644 --- a/ryu/tests/switch/of13/match/30_ICMPV6_CODE.json +++ b/ryu/tests/switch/of13/match/30_ICMPV6_CODE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of14/action/25_SET_FIELD/29_ICMPV6_TYPE.json b/ryu/tests/switch/of14/action/25_SET_FIELD/29_ICMPV6_TYPE.json index 56240928..5c55502f 100644 --- a/ryu/tests/switch/of14/action/25_SET_FIELD/29_ICMPV6_TYPE.json +++ b/ryu/tests/switch/of14/action/25_SET_FIELD/29_ICMPV6_TYPE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of14/action/25_SET_FIELD/30_ICMPV6_CODE.json b/ryu/tests/switch/of14/action/25_SET_FIELD/30_ICMPV6_CODE.json index 9a8570aa..972455ec 100644 --- a/ryu/tests/switch/of14/action/25_SET_FIELD/30_ICMPV6_CODE.json +++ b/ryu/tests/switch/of14/action/25_SET_FIELD/30_ICMPV6_CODE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of14/match/29_ICMPV6_TYPE.json b/ryu/tests/switch/of14/match/29_ICMPV6_TYPE.json index db0dd123..182ee593 100644 --- a/ryu/tests/switch/of14/match/29_ICMPV6_TYPE.json +++ b/ryu/tests/switch/of14/match/29_ICMPV6_TYPE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/of14/match/30_ICMPV6_CODE.json b/ryu/tests/switch/of14/match/30_ICMPV6_CODE.json index 739678d4..aee2edf7 100644 --- a/ryu/tests/switch/of14/match/30_ICMPV6_CODE.json +++ b/ryu/tests/switch/of14/match/30_ICMPV6_CODE.json @@ -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)" ] } ] diff --git a/ryu/tests/switch/tester.py b/ryu/tests/switch/tester.py index d57d8de5..8ff9e966 100644 --- a/ryu/tests/switch/tester.py +++ b/ryu/tests/switch/tester.py @@ -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: From e848eaa57e2532cd2cb298fd58910abc00cedf9d Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Wed, 27 Jun 2018 16:13:25 +0900 Subject: [PATCH 38/93] BGPSpeaker: Enable to specify remote port for neighbor Currently, the remote port of neighbor is the hard-coded value 179. This patch enables to specify the remote port of neighbor in "BGPSpeaker.neighbor_add()" API. Suggested-by: Suresh Kumar Signed-off-by: IWASE Yusuke --- ryu/services/protocols/bgp/bgpspeaker.py | 34 +++++++++++-------- ryu/services/protocols/bgp/peer.py | 2 +- .../protocols/bgp/rtconf/neighbors.py | 18 +++++++++- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/ryu/services/protocols/bgp/bgpspeaker.py b/ryu/services/protocols/bgp/bgpspeaker.py index 46cbcaf1..2f53f636 100644 --- a/ryu/services/protocols/bgp/bgpspeaker.py +++ b/ryu/services/protocols/bgp/bgpspeaker.py @@ -112,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 @@ -406,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, @@ -437,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. @@ -513,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, diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 2c6e3898..f41715eb 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -1283,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' diff --git a/ryu/services/protocols/bgp/rtconf/neighbors.py b/ryu/services/protocols/bgp/rtconf/neighbors.py index 6c481a49..b0853f10 100644 --- a/ryu/services/protocols/bgp/rtconf/neighbors.py +++ b/ryu/services/protocols/bgp/rtconf/neighbors.py @@ -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] From b39ff68f82b2699e1a6498c259f935df961addbe Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 18 Jul 2018 17:40:07 +0900 Subject: [PATCH 39/93] lib/ovs/bridge: Return multiple controllers OVSBridge may have more than one controller. Let get_controller() return a list of controllers in such cases. NOTE: this introduces incompatibility if multiple controllers are configured for a bridge. Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/lib/ovs/bridge.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ryu/lib/ovs/bridge.py b/ryu/lib/ovs/bridge.py index 9753fa29..f86e9ae0 100644 --- a/ryu/lib/ovs/bridge.py +++ b/ryu/lib/ovs/bridge.py @@ -171,7 +171,8 @@ class OVSBridge(object): """ 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): """ From 49b5e5c30a08df65a5a709d1d934142ad658b664 Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Wed, 25 Jul 2018 13:47:48 +0200 Subject: [PATCH 40/93] Fix UT when running in python 3.7 env Due to change [1] in python 3.7 one of ryu's unit tests was failing with this version of interpreter. It was like that because of missing __qualname__ attribute in functools.partial object. This patch fixes it by adding such attribute if it's not set already. [1] https://github.com/python/cpython/pull/4496 Signed-off-by: Slawek Kaplonski Acked-By: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/tests/test_lib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ryu/tests/test_lib.py b/ryu/tests/test_lib.py index 380297bf..344c30a2 100644 --- a/ryu/tests/test_lib.py +++ b/ryu/tests/test_lib.py @@ -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) From 6e9fbad22e250cb4cb903f5c198c0702cd0f971b Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 1 Aug 2018 14:28:49 +0900 Subject: [PATCH 41/93] Bump oslo.config to 2.5.0 Ryu is using item_type since commit f77529036, so oslo.config minimum version needs to be updated. Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- tools/pip-requires | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pip-requires b/tools/pip-requires index 7a131ddf..47c6d02a 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -4,7 +4,7 @@ eventlet!=0.18.3,>=0.18.2,!=0.20.1,!=0.21.0,!=0.23.0 msgpack>=0.3.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 From 19662c5688738a3bc9765b1f7f7886a8da1e2981 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 1 Aug 2018 14:35:19 +0900 Subject: [PATCH 42/93] Test more python versions on travis CI It seems tests weren't correctly run because of interactions between travis CI env and tox venv. Also, run the scenario test on more recent python3, as python3.4 is going away. The test uses a lot of memory and fails with pypy, so it's disabled for now. Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- .travis.yml | 35 ++++++++++++++++++++++++++--------- tox.ini | 4 ++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6ef2609..4f67934d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,31 @@ 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 +matrix: + include: + - python: 3.6 + env: TOX_ENV=pycodestyle + - python: 3.6 + env: TOX_ENV=py36 + - python: 3.6 + env: TOX_ENV=autopep8 + + - python: 2.7 + env: TOX_ENV=pycodestyle + - python: 2.7 + env: TOX_ENV=py27 + + - python: 3.4 + env: TOX_ENV=py34 + + - python: 3.5 + env: TOX_ENV=py35 + + - python: 3.7-dev + env: TOX_ENV=py37 + +# This is disabled because of trouble running on travis CI. +# - python: pypy +# env: TOX_ENV=pypy services: - docker diff --git a/tox.ini b/tox.ini index c1759acb..65136233 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27,py34,py35,pypy26,pycodestyle,autopep8 +envlist = py27,py34,py35,py36,py37,pypy,pycodestyle,autopep8 [testenv] deps = @@ -25,7 +25,7 @@ commands = {[testenv]commands} {[testenv:scenario]commands} -[testenv:py34] +[testenv:py36] commands = {[testenv]commands} {[testenv:scenario]commands} From 840a34884568ecc5c8b111ab3747dc2df4d40868 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Wed, 1 Aug 2018 14:39:50 +0900 Subject: [PATCH 43/93] Declare support of recent python3 versions Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- setup.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.cfg b/setup.cfg index 22737a31..898a7c1d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -16,6 +16,9 @@ classifier = 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 Operating System :: Unix keywords = openflow From a2bcf0a7e61d45deda7e8ec165aa61e648db3ace Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 2 Aug 2018 20:04:48 +0900 Subject: [PATCH 44/93] Ryu 4.27 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index b4625d3b..71db9096 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 26) +version_info = (4, 27) version = '.'.join(map(str, version_info)) From ccedf4cfb305708dd95c9b256af9ec61069eb693 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 30 Mar 2018 11:33:55 +0900 Subject: [PATCH 45/93] mrtlib: Missing subclass for SUBTYPE_RIB_*_MULTICAST Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/mrtlib.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/ryu/lib/mrtlib.py b/ryu/lib/mrtlib.py index 83b4e536..c8f86fc9 100644 --- a/ryu/lib/mrtlib.py +++ b/ryu/lib/mrtlib.py @@ -667,22 +667,44 @@ 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 From 807185470e3ae23297d2cc5ac6438b4bccdcd451 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 30 Mar 2018 11:33:56 +0900 Subject: [PATCH 46/93] mrtlib: Support RFC8050 Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/mrtlib.py | 130 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 116 insertions(+), 14 deletions(-) diff --git a/ryu/lib/mrtlib.py b/ryu/lib/mrtlib.py index c8f86fc9..a89ccfcc 100644 --- a/ryu/lib/mrtlib.py +++ b/ryu/lib/mrtlib.py @@ -431,6 +431,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( @@ -595,7 +600,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 +620,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 +640,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 @@ -709,11 +718,62 @@ class TableDump2RibIPv6MulticastMrtMessage( _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 @@ -729,6 +789,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 @@ -749,7 +812,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 @@ -784,6 +847,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. @@ -795,15 +868,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)) @@ -811,20 +890,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() @@ -832,10 +919,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) @@ -856,6 +950,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) @@ -869,6 +967,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( From bc5bf0dbb658d77a57cd2c2a524c1c53c0cbc4e4 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 30 Mar 2018 11:33:57 +0900 Subject: [PATCH 47/93] test_mrtlib: Test cases for ADD_PATH Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/tests/unit/lib/test_mrtlib.py | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/ryu/tests/unit/lib/test_mrtlib.py b/ryu/tests/unit/lib/test_mrtlib.py index e870f401..55c7cda0 100644 --- a/ryu/tests/unit/lib/test_mrtlib.py +++ b/ryu/tests/unit/lib/test_mrtlib.py @@ -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. From 8312ab23b389d1c2da9c722954c237278b4ee898 Mon Sep 17 00:00:00 2001 From: IWASE Yusuke Date: Fri, 30 Mar 2018 11:33:58 +0900 Subject: [PATCH 48/93] mrtlib: Define JSON representation types Signed-off-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/mrtlib.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/ryu/lib/mrtlib.py b/ryu/lib/mrtlib.py index a89ccfcc..c2d50c6e 100644 --- a/ryu/lib/mrtlib.py +++ b/ryu/lib/mrtlib.py @@ -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, @@ -457,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): @@ -540,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 @@ -937,6 +961,12 @@ class Bgp4MpMrtMessage(MrtMessage): """ MRT Message for the BGP4MP Type. """ + _TYPE = { + 'ascii': [ + 'peer_ip', + 'local_ip', + ], + } @MrtRecord.register_type(MrtRecord.TYPE_BGP4MP) From d7d526ad21993646bfec68daca8c544ecce094bd Mon Sep 17 00:00:00 2001 From: Slawek Kaplonski Date: Sat, 11 Aug 2018 18:46:28 +0200 Subject: [PATCH 49/93] Fix convertion of ipv4 to string on i386 and arch On architectures like i386 or arm convertion of IPv4 to string was failing in some cases. It was like that because some integer values were converted to long which is not the case on x86_64. It was like that for example with value "2871386400" which is used in ryu.tests.unit.ofproto.test_parser_v10:TestOFPMatch unit test. Because of that this test was failing when running on architectures where integer range was too small to handle this value. Signed-off-by: Slawek Kaplonski Reviewed-by: IWASE Yusuke Signed-off-by: FUJITA Tomonori --- ryu/lib/ip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/lib/ip.py b/ryu/lib/ip.py index c4094b9a..c75de162 100644 --- a/ryu/lib/ip.py +++ b/ryu/lib/ip.py @@ -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) From 0031cff9a3e1943161cfad688143c5b0e9911688 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 1 Sep 2018 21:54:08 +0900 Subject: [PATCH 50/93] Ryu 4.28 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index 71db9096..a583da62 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 27) +version_info = (4, 28) version = '.'.join(map(str, version_info)) From e3aa55872b70b97e2fd0946cbd404ef29e2cd092 Mon Sep 17 00:00:00 2001 From: Atzm Watanabe Date: Thu, 13 Sep 2018 12:24:28 +0900 Subject: [PATCH 51/93] app/ofctl: fix possible deadlock when the datapath disconnects Signed-off-by: Atzm Watanabe Reviewed-by: IWAMOTO Toshihiro --- ryu/app/ofctl/service.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py index ce604958..08ee75bd 100644 --- a/ryu/app/ofctl/service.py +++ b/ryu/app/ofctl/service.py @@ -112,6 +112,7 @@ class OfctlService(app_manager.RyuApp): msg = req.msg datapath = msg.datapath parser = datapath.ofproto_parser + is_barrier = isinstance(msg, parser.OFPBarrierRequest) try: si = self._switches[datapath.id] @@ -130,7 +131,16 @@ class OfctlService(app_manager.RyuApp): si.xids[xid] = req si.barriers[barrier_xid] = xid - if isinstance(req.msg, parser.OFPBarrierRequest): + def _cancel(barrier_xid, exc): + xid = si.barriers.pop(barrier_xid) + si.results.pop(xid) + si.xids.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>', msg) + self.reply_to_request(req, event.Reply(exception=exc)) + + if is_barrier: barrier = msg datapath.set_xid(barrier) _store_xid(barrier.xid, barrier.xid) @@ -141,9 +151,13 @@ 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 _cancel(barrier.xid, + exception.InvalidDatapath(result=datapath.id)) - datapath.send_msg(barrier) + if not datapath.send_msg(barrier): + return _cancel(barrier.xid, + exception.InvalidDatapath(result=datapath.id)) @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER) def _handle_barrier(self, ev): From d074e15a480ac6d29d61e511683cc9e03a81c037 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 3 Oct 2018 14:21:56 +0900 Subject: [PATCH 52/93] Ryu 4.29 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index a583da62..b4903c48 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 28) +version_info = (4, 29) version = '.'.join(map(str, version_info)) From 1b38505909a47731e7f7293d08d9ad003ee3787d Mon Sep 17 00:00:00 2001 From: Bill Allen Date: Tue, 16 Oct 2018 21:14:00 +0100 Subject: [PATCH 53/93] Grammatical improvements to some of the documentation. Signed-off-by: Bill Allen Signed-off-by: FUJITA Tomonori --- README.rst | 10 +++---- doc/source/writing_ryu_app.rst | 48 +++++++++++++++++----------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/README.rst b/README.rst index 1a54ae7c..361ef599 100644 --- a/README.rst +++ b/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, @@ -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):: diff --git a/doc/source/writing_ryu_app.rst b/doc/source/writing_ryu_app.rst index 8f8556bb..7f15ed9a 100644 --- a/doc/source/writing_ryu_app.rst +++ b/doc/source/writing_ryu_app.rst @@ -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:: @@ -41,10 +41,10 @@ application. In fact, you can run this Ryu application:: instantiating app /Users/fujita/l2.py -All you have to do is defining needs a new subclass of RyuApp to run +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,20 +103,20 @@ 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 `_. You can learn from the existing Ryu applications at `ryu/app From 56e8fb3f57894bca73f2445de9eb3ce282862f4e Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 3 Nov 2018 19:37:16 +0900 Subject: [PATCH 54/93] Ryu 4.30 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index b4903c48..caa84eec 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 29) +version_info = (4, 30) version = '.'.join(map(str, version_info)) From 01a09a0e0208fe4519885ae2e9bcdbcdbe32aed7 Mon Sep 17 00:00:00 2001 From: IWAMOTO Toshihiro Date: Mon, 25 Mar 2019 14:43:23 +0900 Subject: [PATCH 55/93] Choose the highest TLS version Please note that this is a stop-gap measure. Also add a basic SSL server test. Co-authored-by: alex Signed-off-by: IWAMOTO Toshihiro Signed-off-by: FUJITA Tomonori --- ryu/controller/controller.py | 23 +++++++-- ryu/lib/hub.py | 13 ++++- ryu/tests/unit/controller/cert.crt | 21 ++++++++ ryu/tests/unit/controller/cert.key | 28 +++++++++++ ryu/tests/unit/controller/test_controller.py | 52 ++++++++++++++++++++ 5 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 ryu/tests/unit/controller/cert.crt create mode 100644 ryu/tests/unit/controller/cert.key diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index 62135339..b3d2d35b 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -165,6 +165,23 @@ 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.ca_certs is not None: server = StreamServer((CONF.ofp_listen_host, ofp_ssl_listen_port), @@ -172,15 +189,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), diff --git a/ryu/lib/hub.py b/ryu/lib/hub.py index bd15fc89..e847f656 100644 --- a/ryu/lib/hub.py +++ b/ryu/lib/hub.py @@ -42,6 +42,7 @@ if HUB_TYPE == 'eventlet': import ssl import socket import traceback + import sys getcurrent = eventlet.getcurrent patch = eventlet.monkey_patch @@ -128,7 +129,17 @@ if HUB_TYPE == 'eventlet': if ssl_args: def wrap_and_handle(sock, addr): ssl_args.setdefault('server_side', True) - handle(ssl.wrap_socket(sock, **ssl_args), addr) + 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')) + handle(ctx.wrap_socket(sock, **ssl_args), addr) + else: + handle(ssl.wrap_socket(sock, **ssl_args), addr) self.handle = wrap_and_handle else: diff --git a/ryu/tests/unit/controller/cert.crt b/ryu/tests/unit/controller/cert.crt new file mode 100644 index 00000000..e1b2afc4 --- /dev/null +++ b/ryu/tests/unit/controller/cert.crt @@ -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----- diff --git a/ryu/tests/unit/controller/cert.key b/ryu/tests/unit/controller/cert.key new file mode 100644 index 00000000..2b7f5f06 --- /dev/null +++ b/ryu/tests/unit/controller/cert.key @@ -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----- diff --git a/ryu/tests/unit/controller/test_controller.py b/ryu/tests/unit/controller/test_controller.py index a94e7b43..45c659c9 100644 --- a/ryu/tests/unit/controller/test_controller.py +++ b/ryu/tests/unit/controller/test_controller.py @@ -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,52 @@ 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.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)) From 050bfbc711ed9f3bcab458a904eab74aad90b076 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Mon, 1 Apr 2019 21:39:07 +0900 Subject: [PATCH 56/93] Ryu 4.31 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index caa84eec..e3227b31 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 30) +version_info = (4, 31) version = '.'.join(map(str, version_info)) From 6f906e72c92e10bd0264c9b91a2f7bb85b97780c Mon Sep 17 00:00:00 2001 From: Atzm Watanabe Date: Fri, 29 Mar 2019 13:47:37 +0900 Subject: [PATCH 57/93] app/ofctl: fix possible deadlock When datapath reconnects/disconnects, waiting requests on old datapath should be canceled. Otherwise, threads that sent requests may fall into deadlock because replies possibly never come. Signed-off-by: Atzm Watanabe Signed-off-by: FUJITA Tomonori --- ryu/app/ofctl/service.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/ryu/app/ofctl/service.py b/ryu/app/ofctl/service.py index 08ee75bd..eed51774 100644 --- a/ryu/app/ofctl/service.py +++ b/ryu/app/ofctl/service.py @@ -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,6 +115,8 @@ 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): @@ -131,15 +152,6 @@ class OfctlService(app_manager.RyuApp): si.xids[xid] = req si.barriers[barrier_xid] = xid - def _cancel(barrier_xid, exc): - xid = si.barriers.pop(barrier_xid) - si.results.pop(xid) - si.xids.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>', msg) - self.reply_to_request(req, event.Reply(exception=exc)) - if is_barrier: barrier = msg datapath.set_xid(barrier) @@ -152,12 +164,14 @@ class OfctlService(app_manager.RyuApp): datapath.set_xid(barrier) _store_xid(msg.xid, barrier.xid) if not datapath.send_msg(msg): - return _cancel(barrier.xid, - exception.InvalidDatapath(result=datapath.id)) + return self._cancel( + si, barrier.xid, + exception.InvalidDatapath(result=datapath.id)) if not datapath.send_msg(barrier): - return _cancel(barrier.xid, - exception.InvalidDatapath(result=datapath.id)) + return self._cancel( + si, barrier.xid, + exception.InvalidDatapath(result=datapath.id)) @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER) def _handle_barrier(self, ev): From 6456711a343bd9999491bee2eb059c218170cc50 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 2 May 2019 18:55:39 +0900 Subject: [PATCH 58/93] Ryu 4.32 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index e3227b31..bd6471bf 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 31) +version_info = (4, 32) version = '.'.join(map(str, version_info)) From 550e89067127538ed41ae38128c479af21f75051 Mon Sep 17 00:00:00 2001 From: Ozgur Yurekten Date: Mon, 15 Jul 2019 14:08:25 +0300 Subject: [PATCH 59/93] nx_action_encap and nx_action_decap classes are defined Signed-off-by: Ozgur Yurekten Signed-off-by: FUJITA Tomonori --- ryu/ofproto/nicira_ext.py | 2 ++ ryu/ofproto/nx_actions.py | 74 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/ryu/ofproto/nicira_ext.py b/ryu/ofproto/nicira_ext.py index 9ac673a3..19c8394c 100644 --- a/ryu/ofproto/nicira_ext.py +++ b/ryu/ofproto/nicira_ext.py @@ -63,6 +63,8 @@ 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' diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py index 7f543471..5707ca17 100644 --- a/ryu/ofproto/nx_actions.py +++ b/ryu/ofproto/nx_actions.py @@ -2999,6 +2999,78 @@ 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 @@ -3083,6 +3155,8 @@ def generate(ofp_name, ofpp_name): 'NXFlowSpecMatch', 'NXFlowSpecLoad', 'NXFlowSpecOutput', + 'NXActionEncapNsh', + 'NXActionEncapEther', 'NXActionDecNshTtl', ] vars = locals() From a295810f77238c5c55fc852d4807f0e46a298245 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 18 Jul 2019 20:46:08 +0900 Subject: [PATCH 60/93] fix style errors Signed-off-by: FUJITA Tomonori --- ryu/ofproto/nx_actions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/ryu/ofproto/nx_actions.py b/ryu/ofproto/nx_actions.py index 5707ca17..bdb36406 100644 --- a/ryu/ofproto/nx_actions.py +++ b/ryu/ofproto/nx_actions.py @@ -3034,8 +3034,6 @@ def generate(ofp_name, ofpp_name): msg_pack_into(self._fmt_str, data, 0, self.hdr_size, self.new_pkt_type) return data - - class NXActionEncapNsh(NXAction): """ Encap nsh From bc111ac10dba7aeaf9787b769f94f06502eeaf61 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 1 Aug 2019 16:09:20 +0900 Subject: [PATCH 61/93] Ryu 4.33 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index bd6471bf..434aadb4 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 32) +version_info = (4, 33) version = '.'.join(map(str, version_info)) From 29b8d7d28b447a614fdf5e4c3ec20c4c53ac710b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Thu, 1 Aug 2019 16:27:36 +0900 Subject: [PATCH 62/93] drop Python 3.4 CI test Python 3.4 is officially dead. Signed-off-by: FUJITA Tomonori --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4f67934d..712ffd12 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,6 @@ matrix: - python: 2.7 env: TOX_ENV=py27 - - python: 3.4 - env: TOX_ENV=py34 - - python: 3.5 env: TOX_ENV=py35 From 4e0fc9e72d2048d272787956f648f19fb9e7158c Mon Sep 17 00:00:00 2001 From: Benjamin Villain via Ryu-devel Date: Tue, 24 Sep 2019 08:48:28 +1000 Subject: [PATCH 63/93] Add support for Adj-RIB-Out (draft-ietf-grow-bmp-adj-rib-out-03) Signed-off-by: Benjamin Villain Signed-off-by: FUJITA Tomonori --- ryu/lib/packet/bmp.py | 49 +++++++++++++++++++++++-------- ryu/tests/unit/packet/test_bmp.py | 21 ++++++++++++- 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/ryu/lib/packet/bmp.py b/ryu/lib/packet/bmp.py index 0b4c3b84..1320dd2e 100644 --- a/ryu/lib/packet/bmp.py +++ b/ryu/lib/packet/bmp.py @@ -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 @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/ryu/tests/unit/packet/test_bmp.py b/ryu/tests/unit/packet/test_bmp.py index f93b8014..d0bffecf 100644 --- a/ryu/tests/unit/packet/test_bmp.py +++ b/ryu/tests/unit/packet/test_bmp.py @@ -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, From 0866cb7d48c9ca7e6eaf9c89909fadd6c76f67d3 Mon Sep 17 00:00:00 2001 From: Benjamin Villain via Ryu-devel Date: Tue, 24 Sep 2019 08:52:48 +1000 Subject: [PATCH 64/93] Add support for revised RFC8227 withdraw labels This commit fixes a parsing error when a BGP update contains a "withdraw label" equal to 0x000000 instead of 0x8000000 as stated in RFC 3107. This commits treats both labels as "withdraw label" Signed-off-by: Benjamin Villain Signed-off-by: FUJITA Tomonori --- ryu/lib/packet/bgp.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index 9e501515..89ed191e 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -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) From c776e4cb68600b2ee0a4f38364f4a355502777f1 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 1 Oct 2019 19:42:10 +0900 Subject: [PATCH 65/93] Ryu 4.34 Signed-off-by: FUJITA Tomonori --- ryu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/__init__.py b/ryu/__init__.py index 434aadb4..dae366a0 100644 --- a/ryu/__init__.py +++ b/ryu/__init__.py @@ -14,5 +14,5 @@ # limitations under the License. -version_info = (4, 33) +version_info = (4, 34) version = '.'.join(map(str, version_info)) From e3ebed794332ca23a0f67580fd3230612d9d7b07 Mon Sep 17 00:00:00 2001 From: Adrian Freund Date: Wed, 27 Nov 2019 13:18:39 +0100 Subject: [PATCH 66/93] Restrict tinyrpc to version 0.9.4 as newer versions break python2 support --- tools/pip-requires | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pip-requires b/tools/pip-requires index 47c6d02a..56020060 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -8,5 +8,5 @@ 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 From be289978c7883a8343faee723f6324f52943d23f Mon Sep 17 00:00:00 2001 From: Grant Curell Date: Wed, 1 Apr 2020 10:12:31 -0500 Subject: [PATCH 67/93] Fix two bugs in simple switch 13 examples - dpid with leading 0s would be truncated to less than 16 characters - Response object incorrectly used body type when it should use text --- ryu/app/simple_switch_13.py | 2 +- ryu/app/simple_switch_rest_13.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ryu/app/simple_switch_13.py b/ryu/app/simple_switch_13.py index 06a5d0ed..907425c9 100644 --- a/ryu/app/simple_switch_13.py +++ b/ryu/app/simple_switch_13.py @@ -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) diff --git a/ryu/app/simple_switch_rest_13.py b/ryu/app/simple_switch_rest_13.py index aaf5d509..31f834f0 100644 --- a/ryu/app/simple_switch_rest_13.py +++ b/ryu/app/simple_switch_rest_13.py @@ -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) From c34337684964029ffd4fc5653633892863942fd6 Mon Sep 17 00:00:00 2001 From: Scott Date: Wed, 22 Apr 2020 17:09:47 +1200 Subject: [PATCH 68/93] updated jsonrpc.Session call to have correct arguments for latest version of ovs Signed-off-by: Scott --- ryu/services/protocols/ovsdb/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/services/protocols/ovsdb/client.py b/ryu/services/protocols/ovsdb/client.py index 6ea36842..3f8b4304 100644 --- a/ryu/services/protocols/ovsdb/client.py +++ b/ryu/services/protocols/ovsdb/client.py @@ -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) From 5fd42fff66352137d085de83173b945c674a9033 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Tue, 12 May 2020 14:04:33 +1200 Subject: [PATCH 69/93] Update URLs. --- README.rst | 4 ++-- debian/control | 6 +++--- debian/copyright | 2 +- doc/source/test-of-config-with-linc.rst | 2 +- doc/source/using_with_openstack.rst | 2 +- doc/source/writing_ryu_app.rst | 6 +++--- setup.cfg | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.rst b/README.rst index 361ef599..33d02c84 100644 --- a/README.rst +++ b/README.rst @@ -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 @@ -59,7 +59,7 @@ On Ubuntu(16.04 LTS or later):: Support ======= -Ryu Official site is ``_. +Ryu Official site is ``_. If you have any questions, suggestions, and patches, the mailing list is available at diff --git a/debian/control b/debian/control index 8bcbe683..0d1c1cc5 100644 --- a/debian/control +++ b/debian/control @@ -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 diff --git a/debian/copyright b/debian/copyright index 63d77d3b..f05255cb 100644 --- a/debian/copyright +++ b/debian/copyright @@ -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 diff --git a/doc/source/test-of-config-with-linc.rst b/doc/source/test-of-config-with-linc.rst index 2ff493e5..0f8c8fa4 100644 --- a/doc/source/test-of-config-with-linc.rst +++ b/doc/source/test-of-config-with-linc.rst @@ -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 diff --git a/doc/source/using_with_openstack.rst b/doc/source/using_with_openstack.rst index 5e153486..13bd9a1e 100644 --- a/doc/source/using_with_openstack.rst +++ b/doc/source/using_with_openstack.rst @@ -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. diff --git a/doc/source/writing_ryu_app.rst b/doc/source/writing_ryu_app.rst index 7f15ed9a..a4d1830a 100644 --- a/doc/source/writing_ryu_app.rst +++ b/doc/source/writing_ryu_app.rst @@ -118,9 +118,9 @@ run a Ryu application that does something useful. Is a dumb L2 switch is too dumb? You want to implement a learning L2 switch? Move to `the next step -`_. You +`_. You can learn from the existing Ryu applications at `ryu/app -`_ directory and +`_ directory and `integrated tests -`_ +`_ directory. diff --git a/setup.cfg b/setup.cfg index 898a7c1d..c3757abb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -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 = From 10a9f79c6a17038c00200a9b81040b7dc7fe3005 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Tue, 12 May 2020 16:32:54 +1200 Subject: [PATCH 70/93] Update how to contribute to Ryu. --- CONTRIBUTING.rst | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 11387509..f57d074f 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -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 `_ 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,7 +30,7 @@ features (it's not a must though). Python version and libraries ============================ -* Python 2.7, 3.4, 3.5: +* Python 2.7, 3.5, 3.6, 3.7: Ryu supports multiple Python version. CI tests on Travis-CI is running on these versions. From 814c8a757a570603c3ccce1d19cbe4cea99f4c19 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Sat, 23 May 2020 11:06:19 +1200 Subject: [PATCH 71/93] Add .readthedocs.yml. --- .readthedocs.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .readthedocs.yml diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..b0d6d443 --- /dev/null +++ b/.readthedocs.yml @@ -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 From 3395daccfe49044929c3e1a8e78fb84c40332514 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Mon, 8 Jun 2020 14:30:21 +1200 Subject: [PATCH 72/93] Deprecate using Ryu with older python versions. --- .travis.yml | 5 ----- setup.cfg | 2 -- tox.ini | 5 ----- 3 files changed, 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 712ffd12..0ce5d205 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,11 +9,6 @@ matrix: - python: 3.6 env: TOX_ENV=autopep8 - - python: 2.7 - env: TOX_ENV=pycodestyle - - python: 2.7 - env: TOX_ENV=py27 - - python: 3.5 env: TOX_ENV=py35 diff --git a/setup.cfg b/setup.cfg index c3757abb..e8afa658 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,9 +13,7 @@ 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 diff --git a/tox.ini b/tox.ini index 65136233..25f3ba99 100644 --- a/tox.ini +++ b/tox.ini @@ -20,11 +20,6 @@ commands = commands = python ryu/tests/integrated/run_test.py -[testenv:py27] -commands = - {[testenv]commands} - {[testenv:scenario]commands} - [testenv:py36] commands = {[testenv]commands} From b6bf01a5c95da0de1e6831a3cf41243e69297854 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Mon, 8 Jun 2020 14:30:58 +1200 Subject: [PATCH 73/93] Remove workaround for issue with older python versions. --- setup.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/setup.py b/setup.py index cf2a404d..fee79eb1 100644 --- a/setup.py +++ b/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 From 885db99eebad050cb79ac70f752a42f60ab387da Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Tue, 12 May 2020 15:11:46 +1200 Subject: [PATCH 74/93] We don't support msgpack 1.0.0 yet. --- debian/control | 4 ++-- tools/pip-requires | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index 0d1c1cc5..200b1005 100644 --- a/debian/control +++ b/debian/control @@ -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.3.0), python-msgpack (< 1.0.0), python-netaddr, python-oslo.config (>= 1:1.2.0), python-paramiko, @@ -28,7 +28,7 @@ Section: python Depends: python-eventlet, python-lxml, - python-msgpack (>= 0.3.0), + python-msgpack (>= 0.3.0), python-msgpack (< 1.0.0), python-netaddr, python-oslo.config (>= 1:1.2.0), python-paramiko, diff --git a/tools/pip-requires b/tools/pip-requires index 56020060..2d59b106 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -2,7 +2,7 @@ # following issue. # https://github.com/eventlet/eventlet/issues/401 eventlet!=0.18.3,>=0.18.2,!=0.20.1,!=0.21.0,!=0.23.0 -msgpack>=0.3.0 # RPC library, BGP speaker(net_cntl) +msgpack>=0.3.0,<1.0.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=2.5.0 ovs>=2.6.0 # OVSDB From 7344c15b016401fef2947d27f07a4933a87f5cfb Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Tue, 12 May 2020 15:16:06 +1200 Subject: [PATCH 75/93] pylint --- ryu/tests/unit/lib/test_ofctl_action_match.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/tests/unit/lib/test_ofctl_action_match.py b/ryu/tests/unit/lib/test_ofctl_action_match.py index 11e27f78..9e9f2e46 100644 --- a/ryu/tests/unit/lib/test_ofctl_action_match.py +++ b/ryu/tests/unit/lib/test_ofctl_action_match.py @@ -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) From 9b002e0eece436ad72e2ec8b250620f78277c567 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Tue, 12 May 2020 15:25:05 +1200 Subject: [PATCH 76/93] Update python versions for tox test environments. --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0ce5d205..cf263bc3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,12 @@ matrix: - python: 3.5 env: TOX_ENV=py35 - - python: 3.7-dev + - python: 3.7 env: TOX_ENV=py37 + - python: 3.8 + env: TOX_ENV=py38 + # This is disabled because of trouble running on travis CI. # - python: pypy # env: TOX_ENV=pypy From dea688e5a68c31fcf2e059c1b65a7c0a3fbc6856 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Tue, 12 May 2020 15:41:15 +1200 Subject: [PATCH 77/93] Upgrade to ubuntu bionic. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index cf263bc3..468b67ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +dist: bionic + language: python matrix: From 15382e497216e6f243d9496488e50fcd014e18f2 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Fri, 12 Jun 2020 11:23:03 +1200 Subject: [PATCH 78/93] Don't need to keep our requirements in sync with OpenStack. --- ryu/tests/unit/test_requirements.py | 85 ----------------------------- 1 file changed, 85 deletions(-) delete mode 100644 ryu/tests/unit/test_requirements.py diff --git a/ryu/tests/unit/test_requirements.py b/ryu/tests/unit/test_requirements.py deleted file mode 100644 index c842a0f0..00000000 --- a/ryu/tests/unit/test_requirements.py +++ /dev/null @@ -1,85 +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 six.moves import urllib - -from nose.tools import ok_ - - -LOG = logging.getLogger(__name__) - -MOD_DIR = os.path.dirname('file://' + 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: - response = urllib.request.urlopen(f) - contents = response.read().decode('utf-8') - for r in pkg_resources.parse_requirements(contents): - requirements[r.name] = str(r) - - 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 From 906b3a3ea5a1f2f117c0c0479e578b51a8afa0e3 Mon Sep 17 00:00:00 2001 From: Artem Abramov Date: Fri, 29 Nov 2019 14:39:37 +0300 Subject: [PATCH 79/93] Bugfix now multiple switches can connect with TLS This fixes a bug in RYU StreamServer where SSLContext was modified for each connection. Now the SSLContext of the server socket is modified only once in __init__ --- ryu/lib/hub.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/ryu/lib/hub.py b/ryu/lib/hub.py index e847f656..cac989a5 100644 --- a/ryu/lib/hub.py +++ b/ryu/lib/hub.py @@ -127,21 +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) - 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')) + 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')) + + def wrap_and_handle_ctx(sock, addr): handle(ctx.wrap_socket(sock, **ssl_args), addr) - else: + + 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 + self.handle = wrap_and_handle_ssl else: self.handle = handle From ddb32f678a5e1f0bbbf2cf810bdd16871abb22d9 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Thu, 11 Jun 2020 15:01:42 +1200 Subject: [PATCH 80/93] Add workaround for Python3.7+ eventlet bug. --- ryu/controller/controller.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index b3d2d35b..1506efb4 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -30,6 +30,7 @@ from socket import TCP_NODELAY from socket import SHUT_WR from socket import timeout as SocketTimeout import ssl +import sys from ryu import cfg from ryu.lib import hub @@ -169,6 +170,12 @@ class OpenFlowController(object): # anything less than python 2.7.9 supports only TLSv1 # or less, thus we choose TLSv1 ssl_args = {'ssl_version': ssl.PROTOCOL_TLSv1} + elif sys.version_info >= (3, 7,): + # On Python3.7+ we can't wrap an SSLContext due to this bug: + # https://github.com/eventlet/eventlet/issues/526 + # Lets assume the system has a new enough OpenSSL that + # SSL is fully disabled. + 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 From 7559befd58332544871cf62851c110c00e4ff1c9 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Thu, 11 Jun 2020 16:42:45 +1200 Subject: [PATCH 81/93] Allow user to set cipher list. --- ryu/controller/controller.py | 4 ++++ ryu/tests/unit/controller/test_controller.py | 1 + 2 files changed, 5 insertions(+) diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index 1506efb4..d79f290a 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -68,6 +68,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"'), @@ -189,6 +190,9 @@ class OpenFlowController(object): # 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), diff --git a/ryu/tests/unit/controller/test_controller.py b/ryu/tests/unit/controller/test_controller.py index 45c659c9..ce09ac7e 100644 --- a/ryu/tests/unit/controller/test_controller.py +++ b/ryu/tests/unit/controller/test_controller.py @@ -191,6 +191,7 @@ class TestOpenFlowController(unittest.TestCase): 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() From f1b46fdebee973ac9bd75fe02bae47a9f5004584 Mon Sep 17 00:00:00 2001 From: Brad Cowie Date: Fri, 12 Jun 2020 15:18:59 +1200 Subject: [PATCH 82/93] Add .stickler.yml. --- .stickler.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .stickler.yml diff --git a/.stickler.yml b/.stickler.yml new file mode 100644 index 00000000..7fcbba89 --- /dev/null +++ b/.stickler.yml @@ -0,0 +1,9 @@ +--- +linters: + flake8: + python: 3 + max-line-length: 120 + pep8: + python: 3 + max-line-length: 120 + py3k: From ca597a5e0976c7d51851344010a3b91dd4d58641 Mon Sep 17 00:00:00 2001 From: Michael Haro Date: Mon, 20 Jul 2020 07:20:34 -0700 Subject: [PATCH 83/93] Add support for the MTU ND option. --- ryu/lib/packet/icmpv6.py | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/ryu/lib/packet/icmpv6.py b/ryu/lib/packet/icmpv6.py index a391c087..0c228382 100644 --- a/ryu/lib/packet/icmpv6.py +++ b/ryu/lib/packet/icmpv6.py @@ -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 From 830b49798fc07b63f7888bdcd9dcdc63a663d8bb Mon Sep 17 00:00:00 2001 From: Michael Haro Date: Mon, 20 Jul 2020 07:43:35 -0700 Subject: [PATCH 84/93] Resolve a syntax warning --- ryu/lib/packet/cfm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/lib/packet/cfm.py b/ryu/lib/packet/cfm.py index 0e8c2cf1..cbf9999a 100644 --- a/ryu/lib/packet/cfm.py +++ b/ryu/lib/packet/cfm.py @@ -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 From 8533f7ef3fd5eabe28726dd6f35578e799f9926f Mon Sep 17 00:00:00 2001 From: cglewis Date: Sun, 17 Jan 2021 12:39:21 -0800 Subject: [PATCH 85/93] fix docker tests and print output for python3 --- ryu/tests/unit/lib/ovs/test_vsctl.py | 6 +++--- tools/install_venv.py | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ryu/tests/unit/lib/ovs/test_vsctl.py b/ryu/tests/unit/lib/ovs/test_vsctl.py index 84698eec..92e00f62 100644 --- a/ryu/tests/unit/lib/ovs/test_vsctl.py +++ b/ryu/tests/unit/lib/ovs/test_vsctl.py @@ -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): diff --git a/tools/install_venv.py b/tools/install_venv.py index 29639801..13a5bc17 100644 --- a/tools/install_venv.py +++ b/tools/install_venv.py @@ -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): From 7fc22c00e18deb762227c8f41a60280ffbb47015 Mon Sep 17 00:00:00 2001 From: cglewis Date: Mon, 18 Jan 2021 09:58:44 -0800 Subject: [PATCH 86/93] add github actions for tox tests --- .github/workflows/tests-unit.yml | 25 +++++++++++++++++++++++++ tox.ini | 9 ++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/tests-unit.yml diff --git a/.github/workflows/tests-unit.yml b/.github/workflows/tests-unit.yml new file mode 100644 index 00000000..4fa0b01d --- /dev/null +++ b/.github/workflows/tests-unit.yml @@ -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] + 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_travis.sh + - name: Test with tox + run: NOSE_VERBOSE=0 tox diff --git a/tox.ini b/tox.ini index 25f3ba99..0af2110f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,12 @@ [tox] -envlist = py27,py34,py35,py36,py37,pypy,pycodestyle,autopep8 +envlist = py35,py36,py37,py38,pypy,pycodestyle,autopep8 + +[gh-actions] +python = + 3.5: py35 + 3.6: py36, pycodestyle, autopep8 + 3.7: py37 + 3.8: py38 [testenv] deps = From 0e6ddebe75d754e054b6f49da8729a86303ce795 Mon Sep 17 00:00:00 2001 From: cglewis Date: Mon, 18 Jan 2021 13:06:05 -0800 Subject: [PATCH 87/93] remove travis, move to github actions --- .github/workflows/tests-unit.yml | 2 +- .travis.yml | 40 ------------------- CONTRIBUTING.rst | 4 +- ...all_docker_test_pkg_for_github_actions.sh} | 0 4 files changed, 3 insertions(+), 43 deletions(-) delete mode 100644 .travis.yml rename ryu/tests/integrated/common/{install_docker_test_pkg_for_travis.sh => install_docker_test_pkg_for_github_actions.sh} (100%) diff --git a/.github/workflows/tests-unit.yml b/.github/workflows/tests-unit.yml index 4fa0b01d..0e7a1a05 100644 --- a/.github/workflows/tests-unit.yml +++ b/.github/workflows/tests-unit.yml @@ -20,6 +20,6 @@ jobs: run: | python -m pip install --upgrade pip pip install tox tox-gh-actions coveralls - bash ryu/tests/integrated/common/install_docker_test_pkg_for_travis.sh + bash ryu/tests/integrated/common/install_docker_test_pkg_for_github_actions.sh - name: Test with tox run: NOSE_VERBOSE=0 tox diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 468b67ef..00000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -dist: bionic - -language: python - -matrix: - include: - - python: 3.6 - env: TOX_ENV=pycodestyle - - python: 3.6 - env: TOX_ENV=py36 - - python: 3.6 - env: TOX_ENV=autopep8 - - - python: 3.5 - env: TOX_ENV=py35 - - - python: 3.7 - env: TOX_ENV=py37 - - - python: 3.8 - env: TOX_ENV=py38 - -# This is disabled because of trouble running on travis CI. -# - python: pypy -# env: TOX_ENV=pypy - -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 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index f57d074f..c501f909 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -30,9 +30,9 @@ features (it's not a must though). Python version and libraries ============================ -* Python 2.7, 3.5, 3.6, 3.7: +* Python 3.5, 3.6, 3.7, 3.8: - 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: diff --git a/ryu/tests/integrated/common/install_docker_test_pkg_for_travis.sh b/ryu/tests/integrated/common/install_docker_test_pkg_for_github_actions.sh similarity index 100% rename from ryu/tests/integrated/common/install_docker_test_pkg_for_travis.sh rename to ryu/tests/integrated/common/install_docker_test_pkg_for_github_actions.sh From 0a1e1e81cf3258514467fcdc93998001077267b5 Mon Sep 17 00:00:00 2001 From: Benjamin Beasley Date: Tue, 29 Dec 2020 13:20:48 -0500 Subject: [PATCH 88/93] Bump minimum msgpack verson to 0.4.0, since ryu/lib/rpc.py uses the use_bin_type option to msgpack.Packer --- debian/control | 4 ++-- tools/pip-requires | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index 200b1005..42976b81 100644 --- a/debian/control +++ b/debian/control @@ -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 (< 1.0.0), + python-msgpack (>= 0.4.0), python-msgpack (< 1.0.0), python-netaddr, python-oslo.config (>= 1:1.2.0), python-paramiko, @@ -28,7 +28,7 @@ Section: python Depends: python-eventlet, python-lxml, - python-msgpack (>= 0.3.0), python-msgpack (< 1.0.0), + python-msgpack (>= 0.4.0), python-msgpack (< 1.0.0), python-netaddr, python-oslo.config (>= 1:1.2.0), python-paramiko, diff --git a/tools/pip-requires b/tools/pip-requires index 2d59b106..cc394abb 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -2,7 +2,7 @@ # following issue. # https://github.com/eventlet/eventlet/issues/401 eventlet!=0.18.3,>=0.18.2,!=0.20.1,!=0.21.0,!=0.23.0 -msgpack>=0.3.0,<1.0.0 # RPC library, BGP speaker(net_cntl) +msgpack>=0.4.0,<1.0.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=2.5.0 ovs>=2.6.0 # OVSDB From 8990ed47edc82fb2b7600bf37029d6f770ef1a41 Mon Sep 17 00:00:00 2001 From: Benjamin Beasley Date: Tue, 29 Dec 2020 14:42:30 -0500 Subject: [PATCH 89/93] Enforce new msgpack format (use_bin_type=True) in ryu.services.protocols.bgp.net_ctrl.RpcSession; this option is already used in ryu.lib.rpc.MessageEncoder --- ryu/services/protocols/bgp/net_ctrl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/services/protocols/bgp/net_ctrl.py b/ryu/services/protocols/bgp/net_ctrl.py index 92a8e71e..b79d1265 100644 --- a/ryu/services/protocols/bgp/net_ctrl.py +++ b/ryu/services/protocols/bgp/net_ctrl.py @@ -101,7 +101,7 @@ 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._packer = msgpack.Packer(encoding='utf-8', use_bin_type=True) self._unpacker = msgpack.Unpacker(encoding='utf-8') self._next_msgid = 0 self._socket = sock From aa10cac1db026c8c77354f257300440b55266c9c Mon Sep 17 00:00:00 2001 From: Benjamin Beasley Date: Wed, 30 Dec 2020 09:59:13 -0500 Subject: [PATCH 90/93] Add msgpack 1.0 support; use version testing to preserve compatibility with older versions --- debian/control | 4 ++-- ryu/lib/rpc.py | 12 ++++++++++-- ryu/services/protocols/bgp/net_ctrl.py | 12 ++++++++++-- tools/pip-requires | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/debian/control b/debian/control index 42976b81..fd5af74a 100644 --- a/debian/control +++ b/debian/control @@ -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.4.0), python-msgpack (< 1.0.0), + python-msgpack (>= 0.4.0), python-netaddr, python-oslo.config (>= 1:1.2.0), python-paramiko, @@ -28,7 +28,7 @@ Section: python Depends: python-eventlet, python-lxml, - python-msgpack (>= 0.4.0), python-msgpack (< 1.0.0), + python-msgpack (>= 0.4.0), python-netaddr, python-oslo.config (>= 1:1.2.0), python-paramiko, diff --git a/ryu/lib/rpc.py b/ryu/lib/rpc.py index 7db0ebeb..f74f8846 100644 --- a/ryu/lib/rpc.py +++ b/ryu/lib/rpc.py @@ -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): diff --git a/ryu/services/protocols/bgp/net_ctrl.py b/ryu/services/protocols/bgp/net_ctrl.py index b79d1265..5c79d3f8 100644 --- a/ryu/services/protocols/bgp/net_ctrl.py +++ b/ryu/services/protocols/bgp/net_ctrl.py @@ -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', 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 self._socket = sock self._outgoing_msg_sink_iter = outgoing_msg_sink_iter diff --git a/tools/pip-requires b/tools/pip-requires index cc394abb..6de3cfc2 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -2,7 +2,7 @@ # following issue. # https://github.com/eventlet/eventlet/issues/401 eventlet!=0.18.3,>=0.18.2,!=0.20.1,!=0.21.0,!=0.23.0 -msgpack>=0.4.0,<1.0.0 # RPC library, BGP speaker(net_cntl) +msgpack>=0.4.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=2.5.0 ovs>=2.6.0 # OVSDB From 8740dd97e46ca4cf989e089fa612a1369f059a8d Mon Sep 17 00:00:00 2001 From: cglewis Date: Tue, 19 Jan 2021 17:59:31 -0800 Subject: [PATCH 91/93] add renovate --- .renovaterc.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .renovaterc.json diff --git a/.renovaterc.json b/.renovaterc.json new file mode 100644 index 00000000..e1e004b7 --- /dev/null +++ b/.renovaterc.json @@ -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" + ] +} From afa2f835596761d4633e9eccce0c79d56e960553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20K=C3=A4mmerling?= Date: Mon, 21 Dec 2020 11:47:04 +0100 Subject: [PATCH 92/93] Add Support for Python 3.9 --- .github/workflows/tests-unit.yml | 2 +- CONTRIBUTING.rst | 2 +- setup.cfg | 2 ++ tox.ini | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests-unit.yml b/.github/workflows/tests-unit.yml index 0e7a1a05..0395e44f 100644 --- a/.github/workflows/tests-unit.yml +++ b/.github/workflows/tests-unit.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8] + python-version: [3.5, 3.6, 3.7, 3.8, 3.9] steps: - name: Checkout repo uses: actions/checkout@v2 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c501f909..c2ce5ca3 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -30,7 +30,7 @@ features (it's not a must though). Python version and libraries ============================ -* Python 3.5, 3.6, 3.7, 3.8: +* Python 3.5, 3.6, 3.7, 3.8, 3.9: Ryu supports multiple Python versions. CI tests on GitHub Actions is running on these versions. diff --git a/setup.cfg b/setup.cfg index e8afa658..b3716c1c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,6 +17,8 @@ classifier = 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 diff --git a/tox.ini b/tox.ini index 0af2110f..37b95397 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py35,py36,py37,py38,pypy,pycodestyle,autopep8 +envlist = py35,py36,py37,py38,py39,pypy,pycodestyle,autopep8 [gh-actions] python = @@ -7,6 +7,7 @@ python = 3.6: py36, pycodestyle, autopep8 3.7: py37 3.8: py38 + 3.9: py39 [testenv] deps = From ea4112f39321d8e776f933b067fe9bb683697aa0 Mon Sep 17 00:00:00 2001 From: cglewis Date: Wed, 20 Jan 2021 10:40:50 -0800 Subject: [PATCH 93/93] revert #100, use latest eventlet --- ryu/controller/controller.py | 7 ------- tools/pip-requires | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py index d79f290a..698e375e 100644 --- a/ryu/controller/controller.py +++ b/ryu/controller/controller.py @@ -30,7 +30,6 @@ from socket import TCP_NODELAY from socket import SHUT_WR from socket import timeout as SocketTimeout import ssl -import sys from ryu import cfg from ryu.lib import hub @@ -171,12 +170,6 @@ class OpenFlowController(object): # anything less than python 2.7.9 supports only TLSv1 # or less, thus we choose TLSv1 ssl_args = {'ssl_version': ssl.PROTOCOL_TLSv1} - elif sys.version_info >= (3, 7,): - # On Python3.7+ we can't wrap an SSLContext due to this bug: - # https://github.com/eventlet/eventlet/issues/526 - # Lets assume the system has a new enough OpenSSL that - # SSL is fully disabled. - 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 diff --git a/tools/pip-requires b/tools/pip-requires index 2d59b106..e6c408f5 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,7 +1,7 @@ # 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,!=0.23.0 +eventlet==0.30.0 msgpack>=0.3.0,<1.0.0 # RPC library, BGP speaker(net_cntl) netaddr oslo.config>=2.5.0