[Ryu-devel] [PATCH 03/12] bgp: don't block at start method
Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/application.py |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/services/protocols/bgp/application.py b/ryu/services/protocols/bgp/application.py index 1751e5f..6737d7d 100644 --- a/ryu/services/protocols/bgp/application.py +++ b/ryu/services/protocols/bgp/application.py @@ -102,7 +102,7 @@ class BGPSpeaker(RyuApp): super(BGPSpeaker, self).start() -t.wait() +return t @classmethod def validate_rpc_ip(cls, ip): -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 04/12] packet/bgp: add helper methods to nlri class for bgp ssh client
Signed-off-by: ISHIDA Wataru --- ryu/lib/packet/bgp.py | 44 ++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index 8bcffa8..06323a8 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -716,7 +716,11 @@ class IPAddrPrefix(_UnlabelledAddrPrefix, _IPAddrPrefix): @property def prefix(self): -return self.addr +return self.addr+'/{0}'.format(self.length) + +@property +def formatted_nlri_str(self): +return self.prefix class IP6AddrPrefix(_UnlabelledAddrPrefix, _IP6AddrPrefix): @@ -724,18 +728,54 @@ class IP6AddrPrefix(_UnlabelledAddrPrefix, _IP6AddrPrefix): @property def prefix(self): -return self.addr +return self.addr+'/{0}'.format(self.length) + +@property +def formatted_nlri_str(self): +return self.prefix class LabelledVPNIPAddrPrefix(_LabelledAddrPrefix, _VPNAddrPrefix, _IPAddrPrefix): ROUTE_FAMILY = RF_IPv4_VPN +@property +def prefix(self): +return self.addr[-1]+'/{0}'.format(self.length) + +@property +def route_disc(self): +return self.addr[-2] + +@property +def label_list(self): +return self.addr[:-2] + +@property +def formatted_nlri_str(self): +return "%s:%s" % (self.route_disc, self.prefix) + class LabelledVPNIP6AddrPrefix(_LabelledAddrPrefix, _VPNAddrPrefix, _IP6AddrPrefix): ROUTE_FAMILY = RF_IPv6_VPN +@property +def prefix(self): +return self.addr[-1]+'/{0}'.format(self.length) + +@property +def route_disc(self): +return self.addr[-2] + +@property +def label_list(self): +return self.addr[:-2] + +@property +def formatted_nlri_str(self): +return "%s:%s" % (self.route_disc, self.prefix) + class RouteTargetMembershipNLRI(StringifyMixin): """Route Target Membership NLRI. -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 01/12] bgp: remove unnecessary log message
update msg without MpReachNlri or MpUnReachNlri is now normal Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/peer.py |2 -- 1 file changed, 2 deletions(-) diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 24edf2d..0ee39be 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -986,8 +986,6 @@ class Peer(Source, Sink, NeighborConfListener, Activity): # non-MPBGP Update msg. if not (mp_reach_attr or mp_unreach_attr): -LOG.info('Received UPDATE msg. with no MpReachNlri or ' - 'MpUnReachNlri attribute.') if not self.is_mpbgp_cap_valid(RF_IPv4_UC): LOG.error('Got UPDATE message with un-available' ' afi/safi %s' % RF_IPv4_UC) -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 08/12] packet/bgp: enhanced route refresh support
Enhanced Route Refresh(draft-ietf-idr-bgp-enhanced-route-refresh) uses reserved fields in a Route Refresh message as demarcation fileds. Signed-off-by: ISHIDA Wataru --- ryu/lib/packet/bgp.py | 13 + 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index e488653..a3c852c 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -2142,30 +2142,27 @@ class BGPRouteRefresh(BGPMessage): _MIN_LEN = BGPMessage._HDR_LEN + struct.calcsize(_PACK_STR) def __init__(self, - afi, safi, reserved=0, + afi, safi, demarcation=0, type_=BGP_MSG_ROUTE_REFRESH, len_=None, marker=None): super(BGPRouteRefresh, self).__init__(marker=marker, len_=len_, type_=type_) self.afi = afi self.safi = safi -self.reserved = reserved +self.demarcation = demarcation @classmethod def parser(cls, buf): -(afi, reserved, safi,) = struct.unpack_from(cls._PACK_STR, +(afi, demarcation, safi,) = struct.unpack_from(cls._PACK_STR, buffer(buf)) return { "afi": afi, -"reserved": reserved, "safi": safi, +"demarcation": demarcation, } def serialize_tail(self): -# fixup -self.reserved = 0 - return bytearray(struct.pack(self._PACK_STR, self.afi, - self.reserved, self.safi)) + self.demarcation, self.safi)) class StreamParser(stream_parser.StreamParser): -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 11/12] bgp: fix bug of accessing dead socket
BGP session can be closed by sending inappropriate messages. So touching socket by get_peername() after sending messages may cause an exception. Though we can handle this by try..exception, I fixed to simply call get_peername() before sending messages because session disconnection by sending messages is an ordinary procedure and not an exception(the peer will send notification before disconnection). Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/speaker.py |9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ryu/services/protocols/bgp/speaker.py b/ryu/services/protocols/bgp/speaker.py index a0e2ae5..dc828d1 100644 --- a/ryu/services/protocols/bgp/speaker.py +++ b/ryu/services/protocols/bgp/speaker.py @@ -371,15 +371,18 @@ class BgpProtocol(Protocol, Activity): raise BgpProtocolException('Tried to send message to peer when ' 'this protocol instance is not started' ' or is no longer is started state.') +# get peername before senging msg because sending msg can occur +# conncetion lost +peername = self.get_peername() self._socket.sendall(msg.serialize()) + if msg.type == BGP_MSG_NOTIFICATION: LOG.error('Sent notification to %s >> %s' % - (self.get_peername(), msg)) + (peername, msg)) self._signal_bus.bgp_notification_sent(self._peer, msg) - else: -LOG.debug('Sent msg to %s >> %s' % (self.get_peername(), msg)) +LOG.debug('Sent msg to %s >> %s' % (peername, msg)) def stop(self): Activity.stop(self) -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 05/12] bgp: fix wrong module path
Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/operator/views/bgp.py | 53 +++- ryu/services/protocols/bgp/operator/views/other.py |2 +- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/ryu/services/protocols/bgp/operator/views/bgp.py b/ryu/services/protocols/bgp/operator/views/bgp.py index f78f2a9..bd96443 100644 --- a/ryu/services/protocols/bgp/operator/views/bgp.py +++ b/ryu/services/protocols/bgp/operator/views/bgp.py @@ -11,22 +11,24 @@ from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC from ryu.lib.packet.bgp import BGP_ATTR_TYPE_LOCAL_PREF from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES + class CoreServiceDetailView(OperatorDetailView): rf_state = fields.RelatedViewField( 'rf_state', -'bgpspeaker.operator.views.bgp.RfStateDetailView' +'ryu.services.protocols.bgp.operator.views.bgp.RfStateDetailView' ) importmap_manager = fields.RelatedDictViewField( '_importmap_manager', -'bgpspeaker.operator.views.other.ImportmapManagerDetailView' +'ryu.services.protocols.bgp.operator' +'.views.other.ImportmapManagerDetailView' ) table_manager = fields.RelatedViewField( '_table_manager', -'bgpspeaker.operator.views.bgp.TableManagerDetailView' +'ryu.services.protocols.bgp.operator.views.bgp.TableManagerDetailView' ) peer_manager = fields.RelatedViewField( '_peer_manager', -'bgpspeaker.operator.views.bgp.PeerManagerDetailView' +'ryu.services.protocols.bgp.operator.views.bgp.PeerManagerDetailView' ) router_id = fields.DataField('router_id') @@ -34,15 +36,15 @@ class CoreServiceDetailView(OperatorDetailView): class TableManagerDetailView(OperatorDetailView): tables = fields.RelatedDictViewField( '_tables', -'bgpspeaker.operator.views.bgp.TableDictView' +'ryu.services.protocols.bgp.operator.views.bgp.TableDictView' ) tables_for_rt = fields.RelatedDictViewField( '_tables_for_rt', -'bgpspeaker.operator.views.bgp.TableDictView' +'ryu.services.protocols.bgp.operator.views.bgp.TableDictView' ) global_tables = fields.RelatedDictViewField( '_global_tables', -'bgpspeaker.operator.views.bgp.TableDictView' +'ryu.services.protocols.bgp.operator.views.bgp.TableDictView' ) asbr_label_range = fields.DataField('_asbr_label_range') next_hop_label = fields.DataField('_next_hop_label') @@ -52,11 +54,11 @@ class TableManagerDetailView(OperatorDetailView): class PeerManagerDetailView(OperatorDetailView): peers = fields.RelatedListViewField( '_peers', -'bgpspeaker.operator.views.bgp.PeerDictView' +'ryu.services.protocols.bgp.operator.views.bgp.PeerDictView' ) peers_summary = fields.RelatedListViewField( '_peers', -'bgpspeaker.operator.views.bgp.PeerDictSummaryView' +'ryu.services.protocols.bgp.operator.views.bgp.PeerDictSummaryView' ) @@ -80,15 +82,15 @@ class PeerDetailView(OperatorDetailView): enabled = fields.DataField('enabled') neigh_conf = fields.RelatedViewField( '_neigh_conf', -'bgpspeaker.operator.views.conf.ConfDetailView' +'ryu.services.protocols.bgp.operator.views.conf.ConfDetailView' ) common_conf = fields.RelatedViewField( '_common_conf', -'bgpspeaker.operator.views.conf.ConfDetailView' +'ryu.services.protocols.bgp.operator.views.conf.ConfDetailView' ) state = fields.RelatedViewField( 'state', -'bgpspeaker.operator.views.bgp.PeerStateDetailView' +'ryu.services.protocols.bgp.operator.views.bgp.PeerStateDetailView' ) def encode(self): @@ -113,7 +115,7 @@ class PeerRfDetailView(OperatorDetailView): enabled = fields.DataField('enabled') peer = fields.RelatedViewField( 'peer', -'bgpspeaker.operator.views.bgp.PeerDetailView' +'ryu.services.protocols.bgp.operator.views.bgp.PeerDetailView' ) @@ -122,25 +124,26 @@ class TableDetailView(OperatorDetailView): route_family = fields.DataField('route_family') destinations = fields.RelatedDictViewField( '_destinations', -'bgpspeaker.operator.views.bgp.DestinationDictView' +'ryu.services.protocols.bgp.operator.views.bgp.DestinationDictView' ) class PathDetailView(OperatorDetailView): source_version_num = fields.DataField('source_version_num') route_family = fields.RelatedViewField( -'route_family', 'bgpspeaker.operator.views.bgp.RouteFamilyView' +'route_family', +'ryu.services.protocols.bgp.operator.views.bgp.RouteFamilyView' ) nlri = fields.RelatedViewField( 'nlri', -'bgpspeaker.operator.views.bgp.NlriDetailView' +'ryu.services.protocols.bgp.operator.views.bgp.NlriDetailView' ) is_wit
[Ryu-devel] [PATCH 07/12] packet/bgp: fix bug in serializing AS PATH path attribute
Signed-off-by: ISHIDA Wataru --- ryu/lib/packet/bgp.py |2 ++ 1 file changed, 2 insertions(+) diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index 06323a8..e488653 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -1265,6 +1265,8 @@ class _BGPPathAttributeAsPathCommon(_PathAttribute): type_ = self._AS_SEQUENCE l = list(e) num_as = len(l) +if num_as == 0: +continue msg_pack_into(self._SEG_HDR_PACK_STR, buf, offset, type_, num_as) offset += struct.calcsize(self._SEG_HDR_PACK_STR) for i in l: -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 06/12] bgp: add ssh client
add ssh client which has basic bash keybinds and tab complement. to use, you have to create ssh key at first then specify the location of the key in ryu configuration files. configuration file will be like this. > ryu.conf > == > [DEFAULT] > cli_ssh_hostkey=/home/user/.ssh/id_rsa after this, run operator/ssh.py with application.py $ ryu-manager --config-file=ryu.conf application.py operator/ssh.py you can login by $ ssh ryu@localhost -p 4990 Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/operator/command.py |2 +- .../protocols/bgp/operator/commands/set.py |8 +- .../bgp/operator/commands/show/__init__.py | 11 +- .../protocols/bgp/operator/commands/show/memory.py |2 +- .../protocols/bgp/operator/commands/show/rib.py| 10 +- .../commands/show/route_formatter_mixin.py | 11 +- .../protocols/bgp/operator/internal_api.py | 30 +- ryu/services/protocols/bgp/operator/ssh.py | 472 8 files changed, 529 insertions(+), 17 deletions(-) create mode 100644 ryu/services/protocols/bgp/operator/ssh.py diff --git a/ryu/services/protocols/bgp/operator/command.py b/ryu/services/protocols/bgp/operator/command.py index bd384f0..64449ef 100644 --- a/ryu/services/protocols/bgp/operator/command.py +++ b/ryu/services/protocols/bgp/operator/command.py @@ -42,7 +42,7 @@ class Command(object): help_msg = '' param_help_msg = None command = '' -cli_resp_line_template = '{0}: {1}\n\n' +cli_resp_line_template = '{0}: {1}\n' def __init__(self, api=None, parent=None, help_formatter=default_help_formatter, diff --git a/ryu/services/protocols/bgp/operator/commands/set.py b/ryu/services/protocols/bgp/operator/commands/set.py index b28a80a..c6c9c5d 100644 --- a/ryu/services/protocols/bgp/operator/commands/set.py +++ b/ryu/services/protocols/bgp/operator/commands/set.py @@ -3,6 +3,7 @@ import logging from ryu.services.protocols.bgp.operator.command import Command from ryu.services.protocols.bgp.operator.command import CommandsResponse from ryu.services.protocols.bgp.operator.command import STATUS_OK +from ryu.services.protocols.bgp.operator.command import STATUS_ERROR from ryu.services.protocols.bgp.operator.commands.responses import \ WrongParamResp @@ -19,6 +20,9 @@ class LoggingCmd(Command): 'level': self.Level } +def action(self, params): +return CommandsResponse(STATUS_ERROR, 'Command incomplete') + class On(Command): command = 'on' help_msg = 'turn-on the logging at the current level' @@ -56,10 +60,10 @@ class LoggingCmd(Command): class SetCmd(Command): -help_msg = 'allows to set runtime settings' +help_msg = 'set runtime settings' command = 'set' subcommands = {'logging': LoggingCmd} def action(self, params): -return CommandsResponse(STATUS_OK, True) +return CommandsResponse(STATUS_ERROR, 'Command incomplete') diff --git a/ryu/services/protocols/bgp/operator/commands/show/__init__.py b/ryu/services/protocols/bgp/operator/commands/show/__init__.py index 388a1e7..f0c3072 100644 --- a/ryu/services/protocols/bgp/operator/commands/show/__init__.py +++ b/ryu/services/protocols/bgp/operator/commands/show/__init__.py @@ -1,6 +1,7 @@ from ryu.services.protocols.bgp.operator.command import Command from ryu.services.protocols.bgp.operator.command import CommandsResponse from ryu.services.protocols.bgp.operator.command import STATUS_OK +from ryu.services.protocols.bgp.operator.command import STATUS_ERROR from ryu.services.protocols.bgp.operator.commands.show import count from ryu.services.protocols.bgp.operator.commands.show import importmap from ryu.services.protocols.bgp.operator.commands.show import memory @@ -26,7 +27,7 @@ class ShowCmd(Command): } def action(self, params): -return CommandsResponse(STATUS_OK, None) +return CommandsResponse(STATUS_ERROR, 'Command incomplete') class Count(count.Count): pass @@ -51,6 +52,10 @@ class ShowCmd(Command): help_msg = 'shows if logging is on/off and current logging level.' def action(self, params): -ret = {'logging': self.api.check_logging(), - 'level': self.api.check_logging_level()} +if self.api.check_logging(): +ret = {'logging': self.api.check_logging(), + 'level': self.api.check_logging_level()} +else: +ret = {'logging': self.api.check_logging(), + 'level': None} return CommandsResponse(STATUS_OK, ret) diff --git a/ryu/services/protocols/bgp/operator/commands/show/memory.py b/ryu/services/protocols/bgp/operator/commands/show/memory.py index c519adf..97e7573 100644 --- a/ryu/services/protocols/bgp/operator/commands/show/memory.py +++ b/ryu/services/protocols/bgp/operator/commands/show/memory.py @@ -48,7 +48
[Ryu-devel] [PATCH 10/12] bgp: improve how to show rib
Signed-off-by: ISHIDA Wataru --- .../protocols/bgp/operator/commands/show/rib.py|2 +- .../commands/show/route_formatter_mixin.py | 15 +-- .../protocols/bgp/operator/internal_api.py | 14 ++ ryu/services/protocols/bgp/processor.py|2 +- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/ryu/services/protocols/bgp/operator/commands/show/rib.py b/ryu/services/protocols/bgp/operator/commands/show/rib.py index 34d4a18..94e1657 100644 --- a/ryu/services/protocols/bgp/operator/commands/show/rib.py +++ b/ryu/services/protocols/bgp/operator/commands/show/rib.py @@ -15,7 +15,7 @@ class RibBase(Command, RouteFormatterMixin): class Rib(RibBase): -help_msg = 'show all routes for address family (only vpnv4 supported)' +help_msg = 'show all routes for address family' param_help_msg = '' command = 'rib' diff --git a/ryu/services/protocols/bgp/operator/commands/show/route_formatter_mixin.py b/ryu/services/protocols/bgp/operator/commands/show/route_formatter_mixin.py index 2f58f68..10c56e9 100644 --- a/ryu/services/protocols/bgp/operator/commands/show/route_formatter_mixin.py +++ b/ryu/services/protocols/bgp/operator/commands/show/route_formatter_mixin.py @@ -3,12 +3,14 @@ import StringIO class RouteFormatterMixin(object): +fmtstr = ' {0:<3s} {1:<32s} {2:<20s} {3:<15s} {4:<6s} {5:<6s} {6:<}\n' + @classmethod def _format_family_header(cls): ret = '' ret += ('Status codes: * valid, > best\n') -ret += ' {0:<3s} {1:<32s} {2:<20s} {3:<10s} {4:<20s} {5:<}\n'.format( -'', 'Network', 'Next Hop', 'Reason', 'Metric', 'Path') +ret += cls.fmtstr.format('', 'Network', 'Next Hop', 'Reason', 'Metric', + 'LocPrf', 'Path') return ret @classmethod @@ -24,6 +26,7 @@ class RouteFormatterMixin(object): bpr = path.get('bpr') next_hop = path.get('nexthop') med = path.get('metric') +localpref = path.get('localpref') # Construct path status string. path_status = '*' if is_best: @@ -35,10 +38,10 @@ class RouteFormatterMixin(object): prefix = path.get('prefix') # Append path info to String buffer. -buff.write( -' {0:<3s} {1:<32s} {2:<20s} {3:<20s} {4:<10s} {5:<}\n'. -format(path_status, prefix, next_hop, bpr, str(med), - ' '.join(map(str, aspath +buff.write(cls.fmtstr.format(path_status, prefix, + next_hop, bpr, str(med), + str(localpref), + ' '.join(map(str, aspath for dist in dest_list: for idx, path in enumerate(dist.get('paths')): diff --git a/ryu/services/protocols/bgp/operator/internal_api.py b/ryu/services/protocols/bgp/operator/internal_api.py index c98ab69..c3a420e 100644 --- a/ryu/services/protocols/bgp/operator/internal_api.py +++ b/ryu/services/protocols/bgp/operator/internal_api.py @@ -10,6 +10,7 @@ from ryu.lib.packet.bgp import RF_RTC_UC from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH from ryu.lib.packet.bgp import BGP_ATTR_TYPE_MULTI_EXIT_DISC +from ryu.lib.packet.bgp import BGP_ATTR_TYPE_LOCAL_PREF from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_IGP from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_EGP @@ -110,14 +111,13 @@ class InternalApi(object): else: aspath = '' -origin = path.get_pattr(BGP_ATTR_TYPE_ORIGIN).value +origin = path.get_pattr(BGP_ATTR_TYPE_ORIGIN) +origin = origin.value if origin else None if origin == BGP_ATTR_ORIGIN_IGP: origin = 'i' elif origin == BGP_ATTR_ORIGIN_EGP: origin = 'e' -else: -origin = None nexthop = path.nexthop.value # Get the MED path attribute @@ -125,13 +125,19 @@ class InternalApi(object): med = med.value if med else '' # Get best path reason bpr = dst.best_path_reason if path == dst.best_path else '' + +# Get local preference +localpref = path.get_pattr(BGP_ATTR_TYPE_LOCAL_PREF) +localpref = localpref.value if localpref else '' + return {'best': (path == dst.best_path), 'bpr': bpr, 'prefix': path.nlri.formatted_nlri_str, 'nexthop': nexthop, 'metric': med, 'aspath': aspath, -'origin': origin} +'origin': origin, +'localpref': localpref} for path in dst.known_path_list: ret['paths'].append(_path_to_dict(dst, path)
[Ryu-devel] [PATCH 02/12] bgp: bug fix when the peer initiated the connection.
set binded ip and port properly regardless of the direction of connection Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/core.py |3 +++ ryu/services/protocols/bgp/peer.py |3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ryu/services/protocols/bgp/core.py b/ryu/services/protocols/bgp/core.py index f38ece1..06557cf 100644 --- a/ryu/services/protocols/bgp/core.py +++ b/ryu/services/protocols/bgp/core.py @@ -400,7 +400,10 @@ class CoreService(Factory, Activity): """ assert socket peer_addr, peer_port = socket.getpeername() +bind_ip, bind_port = socket.getsockname() peer = self._peer_manager.get_by_addr(peer_addr) +peer._host_bind_ip = bind_ip +peer._host_bind_port = bind_port bgp_proto = self.build_protocol(socket) # We reject this connection request from peer: diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 0ee39be..2f25d3d 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -818,9 +818,6 @@ class Peer(Source, Sink, NeighborConfListener, Activity): client_factory, time_out=tcp_conn_timeout, bind_address=bind_addr) -bind_ip, bind_port = sock.getpeername() -self._host_bind_ip = bind_ip -self._host_bind_port = bind_port except socket.error: self.state.bgp_state = const.BGP_FSM_ACTIVE LOG.debug('Socket could not be created in time (%s secs),' -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 12/12] packet/bgp: bug fix of route target nlri class
Signed-off-by: ISHIDA Wataru --- ryu/lib/packet/bgp.py | 49 +++-- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py index a3c852c..6882770 100644 --- a/ryu/lib/packet/bgp.py +++ b/ryu/lib/packet/bgp.py @@ -790,22 +790,59 @@ class RouteTargetMembershipNLRI(StringifyMixin): def __init__(self, origin_as, route_target): # If given is not default_as and default_rt -if not (origin_as is RtNlri.DEFAULT_AS and -route_target is RtNlri.DEFAULT_RT): +if not (origin_as is self.DEFAULT_AS and +route_target is self.DEFAULT_RT): # We validate them -if (not is_valid_old_asn(origin_as) or -not is_valid_ext_comm_attr(route_target)): +if (not self._is_valid_old_asn(origin_as) or +not self._is_valid_ext_comm_attr(route_target)): raise ValueError('Invalid params.') self.origin_as = origin_as self.route_target = route_target +def _is_valid_old_asn(self, asn): +"""Returns true if given asn is a 16 bit number. + +Old AS numbers are 16 but unsigned number. +""" +valid = True +# AS number should be a 16 bit number +if (not isinstance(asn, (int, long)) or (asn < 0) or +(asn > ((2 ** 16) - 1))): +valid = False + +return valid + +def _is_valid_ext_comm_attr(self, attr): +"""Validates *attr* as string representation of RT or SOO. + +Returns True if *attr* is as per our convention of RT or SOO, else +False. Our convention is to represent RT/SOO is a string with format: +*global_admin_part:local_admin_path* +""" +is_valid = True + +if not isinstance(attr, str): +is_valid = False +else: +first, second = attr.split(':') +try: +if '.' in first: +socket.inet_aton(first) +else: +int(first) +int(second) +except (ValueError, socket.error): +is_valid = False + +return is_valid + @property def formatted_nlri_str(self): return "%s:%s" % (self.origin_as, self.route_target) def is_default_rtnlri(self): -if (self._origin_as is RtNlri.DEFAULT_AS and -self._route_target is RtNlri.DEFAULT_RT): +if (self._origin_as is self.DEFAULT_AS and +self._route_target is self.DEFAULT_RT): return True return False -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
Re: [Ryu-devel] Does Ryu support SNMP
> Hi, Developers, > > In addition to control OF switch, I have some issue to adapt SNMP to > trigger legacy switch simultaneously. > > I google on the Web and found some patch for Ryu to support SNMP, but I do > not found this patch in the latest V3.9 release. > > https://www.mail-archive.com/ryu-devel@lists.sourceforge.net/msg02783.html > https://www.mail-archive.com/ryu-devel@lists.sourceforge.net/msg02808.html > > Does it mean that snmp agent patch is not included in the Ryu controller? these patches have not been merged. (yet?) YAMAMOTO Takashi > Or did anyone use this snmp patch before, can you share your experience? > > Thanks for your help. > > Best regards > > Jimmy -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
Re: [Ryu-devel] ?????? Error of Executing Traffic Monitor
> Hi Arjen and guys, > > > Thank you so much for your kind reminder. After reading you email, I just > realized that I have used port 6633 for another application. Then I just run > simple_monitor.py, one app at a time...However, there is another report, said > that there is no attribute "datapaths". > do you have local mods in simple_monitor.py? YAMAMOTO Takashi > > Does anyone has some ideas about it? > > > Best regards, and thanks a lot! > Yuan > > > > > > -- 圻兵喨周 -- > 窟周繁: "i3D.net - Arjen Noordhuis";; > 窟僕扮寂: 2014定5埖4晩(佛豚爺) 絡貧6:08 > 辺周繁: "Yuan"<464600...@qq.com>; "Ryu-devel"; > > 麼籾: Re: [Ryu-devel] Error of Executing Traffic Monitor > > > > Hi Yuan, > > I've had this error as well and it took me a while to figure out how to solve > it. The error is caused due a socket from another program that is already > bound to the portnumber commonly used by OpenFlow controllers (port 6633). In > my case I had installed both openvswitch and Ryu on the same server. The > problem is with the package openvswitch-controller, that has been installed > along the actual (openv)switch. Since the openvswitch-controller is > automatically started when openvswitch is started and binds to the openflow > controller port. To find out which program is bound to the port, use "netstat > -tulpen". > > In my case, I did not need the openvswitch-controller package, so I removed > it by using "apt-get remove openvswitch-controller". The error hasn't occured > since then. > > Hopefully this will solve your problem with Ryu as well and you can start > exploring the magic of Ryu. Good luck! > > Best regards, > > Arjen Noordhuis > > > > Yuan <464600...@qq.com> , 5/4/2014 10:18 AM: > Hi guys, > > > I was executing the traffic monitor as the Ryubook suggested on page 24. > However, I confronted error report as the pic showed below. I have been > trying to solve it for 2 days. Python and SDN are totally new for me. I > really need help from you. Plz help me > > > Thanks, > Yuan > > > > > > > -- > > "Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE > Instantly run your Selenium tests across 300+ browser/OS combos. Get > unparalleled scalability from the best Selenium testing platform available. > Simple to use. Nothing to install. Get started now for free." > http://p.sf.net/sfu/SauceLabs > > ___ > Ryu-devel mailing list > Ryu-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/ryu-devel -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 09/12] bgp: fix typo
Signed-off-by: ISHIDA Wataru --- ryu/services/protocols/bgp/peer.py |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py index 2f25d3d..0779206 100644 --- a/ryu/services/protocols/bgp/peer.py +++ b/ryu/services/protocols/bgp/peer.py @@ -455,7 +455,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity): Update appropriate counters and set appropriate timers. """ -assert rr_msg.TYPE_CODE == BGP_MSG_ROUTE_REFRESH +assert rr_msg.type == BGP_MSG_ROUTE_REFRESH self._protocol.send(rr_msg) LOG.debug('RouteRefresh %s>> %s' % (self._neigh_conf.ip_address, rr_msg)) -- 1.7.9.5 -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 1/3] Added ovs-vsctl commands of QoS-related
Here is added the command of QoS-related, such as the following: ovs-vsctl -- set port eth1 qos=@newqos \ -- --id=@newqos create qos type=linux-htb other-config:max-rate=3000 queues=0=@q0,1=@q1 \ -- --id=@q0 create queue other-config:min-rate=100 other-config:max-rate=100 \ -- --id=@q1 create queue other-config:min-rate=200 other-config:max-rate=200 Also, operation that delete QoS is supported. Note that It supports only deletion of relationships with QoS record. Signed-off-by: Kiyonari Harigae --- ryu/lib/ovs/bridge.py | 21 ++ ryu/lib/ovs/vsctl.py | 184 -- 2 files changed, 200 insertions(+), 5 deletions(-) diff --git a/ryu/lib/ovs/bridge.py b/ryu/lib/ovs/bridge.py index cc43646..92dc28b 100644 --- a/ryu/lib/ovs/bridge.py +++ b/ryu/lib/ovs/bridge.py @@ -39,6 +39,7 @@ class OVSBridgeNotFound(ryu_exc.RyuException): class VifPort(object): + def __init__(self, port_name, ofport, vif_id, vif_mac, switch): super(VifPort, self).__init__() self.port_name = port_name @@ -60,6 +61,7 @@ class VifPort(object): class TunnelPort(object): + def __init__(self, port_name, ofport, tunnel_type, local_ip, remote_ip): super(TunnelPort, self).__init__() self.port_name = port_name @@ -88,6 +90,7 @@ class TunnelPort(object): class OVSBridge(object): + def __init__(self, CONF, datapath_id, ovsdb_addr, timeout=None, exception=None): super(OVSBridge, self).__init__() @@ -257,3 +260,21 @@ class OVSBridge(object): if command.result: return command.result[0] return None + +def set_qos(self, port_name, type='linux-htb', max_rate=None, queues=[]): +command_qos = ovs_vsctl.VSCtlCommand( +'set-qos', +[port_name, type, max_rate]) +command_queue = ovs_vsctl.VSCtlCommand( +'set-queue', +[port_name, queues]) +self.run_command([command_qos, command_queue]) +if command_qos.result and command_queue.result: +return command_qos.result + command_queue.result +return None + +def del_qos(self, port_name): +command = ovs_vsctl.VSCtlCommand( +'del-qos', +[port_name]) +self.run_command([command]) diff --git a/ryu/lib/ovs/vsctl.py b/ryu/lib/ovs/vsctl.py index 420c48c..5e57fbc 100644 --- a/ryu/lib/ovs/vsctl.py +++ b/ryu/lib/ovs/vsctl.py @@ -133,12 +133,12 @@ def vsctl_fatal(msg): class VSCtlBridge(object): + def __init__(self, ovsrec_bridge, name, parent, vlan): super(VSCtlBridge, self).__init__() self.br_cfg = ovsrec_bridge self.name = name self.ports = set() - self.parent = parent self.vlan = vlan self.children = set() # WeakSet is needed? @@ -148,22 +148,43 @@ class VSCtlBridge(object): class VSCtlPort(object): + def __init__(self, vsctl_bridge_parent, ovsrec_port): super(VSCtlPort, self).__init__() self.bridge = weakref.ref(vsctl_bridge_parent) # backpointer self.port_cfg = ovsrec_port self.ifaces = set() +self.qos = None class VSCtlIface(object): + def __init__(self, vsctl_port_parent, ovsrec_iface): super(VSCtlIface, self).__init__() self.port = weakref.ref(vsctl_port_parent) # backpointer self.iface_cfg = ovsrec_iface +class VSCtlQoS(object): + +def __init__(self, vsctl_port_parent, ovsrec_qos): +super(VSCtlQoS, self).__init__() +self.port = weakref.ref(vsctl_port_parent) +self.qos_cfg = ovsrec_qos +self.queues = set() + + +class VSCtlQueue(object): + +def __init__(self, vsctl_qos_parent, ovsrec_queue): +super(VSCtlQueue, self).__init__() +self.qos = weakref.ref(vsctl_qos_parent) +self.queue_cfg = ovsrec_queue + + class VSCtlContext(object): + def _invalidate_cache(self): self.cache_valid = False self.bridges.clear() @@ -230,6 +251,11 @@ class VSCtlContext(object): del self.bridges[vsctl_bridge.name] +def del_cached_qos(self, vsctl_qos): +vsctl_qos.port().qos = None +vsctl_qos.port = None +vsctl_qos.queues = None + def add_port_to_cache(self, vsctl_bridge_parent, ovsrec_port): tag = getattr(ovsrec_port, vswitch_idl.OVSREC_PORT_COL_TAG, None) if (tag is not None and tag >= 0 and tag < 4096): @@ -255,6 +281,15 @@ class VSCtlContext(object): vsctl_port_parent.ifaces.add(vsctl_iface) self.ifaces[ovsrec_iface.name] = vsctl_iface +def add_qos_to_cache(self, vsctl_port_parent, ovsrec_qos): +vsctl_qos = VSCtlQoS(vsctl_port_parent, ovsrec_qos) +vsctl_port_parent.qos = vsctl_qos +return vsctl_qos + +def add_queue_to_cache(self, vsctl_qos_parent, ovsrec_queue): +vsctl_queue = VSCtlQueue(vsctl_qos_parent, ovsrec_queue) +
[Ryu-devel] [PATCH 0/3] Added QoS-related modules
Hi, Here is proposing an implementation of QoS-related modules. Detailed description can be found in the commit descriptions and in the changelog of each patch. Kiyonari Harigae (3): Added ovs-vsctl commands of QoS-related Added queue stats request Added rest_qos module ryu/app/rest_qos.py | 1180 + ryu/lib/ofctl_v1_2.py | 22 + ryu/lib/ofctl_v1_3.py | 22 + ryu/lib/ovs/bridge.py | 21 + ryu/lib/ovs/vsctl.py | 184 +++- 5 files changed, 1424 insertions(+), 5 deletions(-) create mode 100644 ryu/app/rest_qos.py -- 1.7.12.4 (Apple Git-37) -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 2/3] Added queue stats request
Here is added queue status request to ofctl. Signed-off-by: Kiyonari Harigae --- ryu/lib/ofctl_v1_2.py | 22 ++ ryu/lib/ofctl_v1_3.py | 22 ++ 2 files changed, 44 insertions(+) diff --git a/ryu/lib/ofctl_v1_2.py b/ryu/lib/ofctl_v1_2.py index ea24fe9..76e5520 100644 --- a/ryu/lib/ofctl_v1_2.py +++ b/ryu/lib/ofctl_v1_2.py @@ -504,6 +504,28 @@ def get_desc_stats(dp, waiters): return desc +def get_queue_stats(dp, waiters): +ofp = dp.ofproto +stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, 0, ofp.OFPP_ANY, + ofp.OFPQ_ALL) +msgs = [] +send_stats_request(dp, stats, waiters, msgs) + +s = [] +for msg in msgs: +stats = msg.body +for stat in stats: +s.append({'duration_nsec': stat.duration_nsec, + 'duration_sec': stat.duration_sec, + 'port_no': stat.port_no, + 'queue_id': stat.queue_id, + 'tx_bytes': stat.tx_bytes, + 'tx_errors': stat.tx_errors, + 'tx_packets': stat.tx_packets}) +desc = {str(dp.id): s} +return desc + + def get_flow_stats(dp, waiters): table_id = dp.ofproto.OFPTT_ALL out_port = dp.ofproto.OFPP_ANY diff --git a/ryu/lib/ofctl_v1_3.py b/ryu/lib/ofctl_v1_3.py index 63356cd..d97da8a 100644 --- a/ryu/lib/ofctl_v1_3.py +++ b/ryu/lib/ofctl_v1_3.py @@ -554,6 +554,28 @@ def get_desc_stats(dp, waiters): return desc +def get_queue_stats(dp, waiters): +ofp = dp.ofproto +stats = dp.ofproto_parser.OFPQueueStatsRequest(dp, 0, ofp.OFPP_ANY, + ofp.OFPQ_ALL) +msgs = [] +send_stats_request(dp, stats, waiters, msgs) + +s = [] +for msg in msgs: +stats = msg.body +for stat in stats: +s.append({'duration_nsec': stat.duration_nsec, + 'duration_sec': stat.duration_sec, + 'port_no': stat.port_no, + 'queue_id': stat.queue_id, + 'tx_bytes': stat.tx_bytes, + 'tx_errors': stat.tx_errors, + 'tx_packets': stat.tx_packets}) +desc = {str(dp.id): s} +return desc + + def get_flow_stats(dp, waiters): table_id = dp.ofproto.OFPTT_ALL flags = 0 -- 1.7.12.4 (Apple Git-37) -- Is your legacy SCM system holding you back? Join Perforce May 7 to find out: • 3 signs your SCM is hindering your productivity • Requirements for releasing software faster • Expert tips and advice for migrating your SCM now http://p.sf.net/sfu/perforce ___ Ryu-devel mailing list Ryu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ryu-devel
[Ryu-devel] [PATCH 3/3] Added rest_qos module
Here is implementation of QoS-related REST API. This module is intended for operation in a pipeline on a flow table. It supports setting of the queue, (Currently, only support OpenvSwitch) , packet marking, queuing, regitation to meter table, perform this simple QoS. Signed-off-by: Kiyonari Harigae --- ryu/app/rest_qos.py | 1180 +++ 1 file changed, 1180 insertions(+) create mode 100644 ryu/app/rest_qos.py diff --git a/ryu/app/rest_qos.py b/ryu/app/rest_qos.py new file mode 100644 index 000..d6d9af4 --- /dev/null +++ b/ryu/app/rest_qos.py @@ -0,0 +1,1180 @@ +# Copyright (C) 2014 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 json +import re + +from webob import Response + +from ryu.app import conf_switch_key as cs_key +from ryu.app.wsgi import ControllerBase +from ryu.app.wsgi import WSGIApplication +from ryu.base import app_manager +from ryu.controller import conf_switch +from ryu.controller import ofp_event +from ryu.controller import dpset +from ryu.controller.handler import set_ev_cls +from ryu.controller.handler import MAIN_DISPATCHER +from ryu.exception import OFPUnknownVersion +from ryu.lib import dpid as dpid_lib +from ryu.lib import mac +from ryu.lib import ofctl_v1_0 +from ryu.lib import ofctl_v1_2 +from ryu.lib import ofctl_v1_3 +from ryu.lib.ovs import bridge +from ryu.ofproto import ofproto_v1_0 +from ryu.ofproto import ofproto_v1_2 +from ryu.ofproto import ofproto_v1_3 +from ryu.ofproto import ofproto_v1_3_parser +from ryu.ofproto import ether +from ryu.ofproto import inet + + +#= +# REST API +#= +# +# Note: specify switch and vlan group, as follows. +# {switch-id} : 'all' or switchID +# {vlan-id} : 'all' or vlanID +# +# about queue status +# +# get status of queue +# GET /qos/queue/status/{switch-id} +# +# about queues +# get a queue configurations +# GET /qos/queue/{switch-id} +# +# set a queue to the switches +# POST /qos/queue/{switch-id} +# +# request body format: +# {"type": "", +# "max-rate": "", +# "queues":[{"max_rate": "", "min_rate": ""},...]} +# +# Note: This operation override +# previous configurations. +# Note: Queue configurations are available for +# OpenvSwitch. +# +# delete queue +# DELETE /qos/queue/{swtich-id} +# +# Note: This operation delete relation of qos record from +# qos colum in Port table. Therefore, +# QoS records and Queue records will remain. +# +# about qos rules +# +# get rules of qos +# * for no vlan +# GET /qos/rules/{switch-id} +# +# * for specific vlan group +# GET /qos/rules/{switch-id}/{vlan-id} +# +# set a qos rules +# +# QoS rules will do the processing pipeline, +# which entries are register the first table (by default table id 0) +# and process will apply and go to next table. +# +# * for no vlan +# POST /qos/{switch-id}/{vlan-id} +# +# * for specific vlan group +# POST /qos/{switch-id}/{vlan-id} +# +# request body format: +# {"match": {"": "", "": "",...}, +#"actions": {"": "", "": "",...} +# } +# +# Description +#* match field +# : +#"priority": "0 to 65533" +#"in_port" : "" +#"dl_src" : "" +#"dl_dst" : "" +#"dl_type" : "" +#"nw_src" : "" +#"nw_dst" : "" +#"ipv6_src": "" +#"ipv6_dst": "" +#"nw_proto": "" +#"tp_src" : "" +#"tp_dst" : "" +#"dscp": "" +# +#* action field +#"mark": +#sets the IPv4 ToS/DSCP field to tos. +#"meter": +#apply meter entry +#"queue": +#register queue specified by queue-id +# +# Note: When "actions" has not been set up, +# "queue: 0" is set to "actions". +# +# delete a qos rules +# * for no vlan +# DELETE /qos/rule/{switch-id} +# +# * for specific vlan group +# DELETE /qos/{switch-id}/{vlan-id} +# +# request body format: +# {"":""} +# +# : +#"qos_id" : "" or "all" +# +# about meter entries +# +# set a meter entry +# POST /qos/meter/{switch-id} +# +# request body format: +# {"meter_id": , +#"bands":[{"action": "", +# "flag": ", +# "rate": , +# "prec_level": },...]} +# +# delete a meter entry +# DELETE /qos/meter/{switch-id} +# +# request body format: +# {"":""} +# +# : +#"meter_id" : "" +# + + +SWITCHID_PATTERN = dpid_lib.DPID_PATTERN + r'|all' +VLANID_PATTERN = r'[0-9]{1,4}|all' + +