mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-05-11 07:16:10 +02:00
lib/ofctl: Add utility library for ofctl_v1_*.py
This patch enables ofctl_v1_*.py to use the reserved OpenFlow
numbers (e.g. port numbering such as "OFPP_CONTROLLER") in the
request and reply parameters of ofctl_rest.py.
Example:
- When adding a flow entry:
$ curl -X POST -d '{
"dpid": 1,
"actions":[
{
"type": "OUTPUT",
"port": "CONTROLLER"
}
]
}' http://localhost:8080/stats/flowentry/add
- When getting flows stats:
$ curl -X GET http://localhost:8080/stats/flow/1
{
"1": [
{
...
"actions": [
"OUTPUT:CONTROLLER"
],
...
}
]
}
Suggested-by: Sergio Andres Rivera Polanco <sergiorivera88@gmail.com>
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
9571fde7dd
commit
19e49c861f
92
ryu/lib/ofctl_utils.py
Normal file
92
ryu/lib/ofctl_utils.py
Normal file
@ -0,0 +1,92 @@
|
||||
# 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
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def str_to_int(str_num):
|
||||
return int(str(str_num), 0)
|
||||
|
||||
|
||||
class OFCtlUtil(object):
|
||||
|
||||
def __init__(self, ofproto):
|
||||
self.ofproto = ofproto
|
||||
|
||||
def _reserved_num_from_user(self, num, prefix):
|
||||
if isinstance(num, int):
|
||||
return num
|
||||
else:
|
||||
if num.startswith(prefix):
|
||||
return getattr(self.ofproto, num)
|
||||
else:
|
||||
return getattr(self.ofproto, prefix + num.upper())
|
||||
|
||||
def _reserved_num_to_user(self, num, prefix):
|
||||
for k, v in self.ofproto.__dict__.items():
|
||||
if k.startswith(prefix) and v == num:
|
||||
return k.replace(prefix, '')
|
||||
return num
|
||||
|
||||
def ofp_port_from_user(self, port):
|
||||
return self._reserved_num_from_user(port, 'OFPP_')
|
||||
|
||||
def ofp_port_to_user(self, port):
|
||||
return self._reserved_num_to_user(port, 'OFPP_')
|
||||
|
||||
def ofp_table_from_user(self, table):
|
||||
return self._reserved_num_from_user(table, 'OFPTT_')
|
||||
|
||||
def ofp_table_to_user(self, table):
|
||||
return self._reserved_num_to_user(table, 'OFPTT_')
|
||||
|
||||
def ofp_cml_from_user(self, max_len):
|
||||
return self._reserved_num_from_user(max_len, 'OFPCML_')
|
||||
|
||||
def ofp_cml_to_user(self, max_len):
|
||||
return self._reserved_num_to_user(max_len, 'OFPCML_')
|
||||
|
||||
def ofp_group_from_user(self, group):
|
||||
return self._reserved_num_from_user(group, 'OFPG_')
|
||||
|
||||
def ofp_group_to_user(self, group):
|
||||
return self._reserved_num_to_user(group, 'OFPG_')
|
||||
|
||||
def ofp_buffer_from_user(self, buffer):
|
||||
if buffer in ['OFP_NO_BUFFER', 'NO_BUFFER']:
|
||||
return self.ofproto.OFP_NO_BUFFER
|
||||
else:
|
||||
return buffer
|
||||
|
||||
def ofp_buffer_to_user(self, buffer):
|
||||
if self.ofproto.OFP_NO_BUFFER == buffer:
|
||||
return 'NO_BUFFER'
|
||||
else:
|
||||
return buffer
|
||||
|
||||
def ofp_meter_from_user(self, meter):
|
||||
return self._reserved_num_from_user(meter, 'OFPM_')
|
||||
|
||||
def ofp_meter_to_user(self, meter):
|
||||
return self._reserved_num_to_user(meter, 'OFPM_')
|
||||
|
||||
def ofp_queue_from_user(self, queue):
|
||||
return self._reserved_num_from_user(queue, 'OFPQ_')
|
||||
|
||||
def ofp_queue_to_user(self, queue):
|
||||
return self._reserved_num_to_user(queue, 'OFPQ_')
|
||||
@ -19,6 +19,7 @@ import logging
|
||||
|
||||
from ryu.ofproto import ofproto_v1_0
|
||||
from ryu.lib import hub
|
||||
from ryu.lib import ofctl_utils
|
||||
from ryu.lib.mac import haddr_to_bin, haddr_to_str
|
||||
|
||||
|
||||
@ -26,13 +27,16 @@ LOG = logging.getLogger('ryu.lib.ofctl_v1_0')
|
||||
|
||||
DEFAULT_TIMEOUT = 1.0 # TODO:XXX
|
||||
|
||||
UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_0)
|
||||
|
||||
|
||||
def to_actions(dp, acts):
|
||||
actions = []
|
||||
for a in acts:
|
||||
action_type = a.get('type')
|
||||
if action_type == 'OUTPUT':
|
||||
port = int(a.get('port', ofproto_v1_0.OFPP_NONE))
|
||||
port = UTIL.ofp_port_from_user(
|
||||
a.get('port', ofproto_v1_0.OFPP_NONE))
|
||||
# NOTE: The reason of this magic number (0xffe5)
|
||||
# is because there is no good constant in of1.0.
|
||||
# The same value as OFPCML_MAX of of1.2 and of1.3 is used.
|
||||
@ -68,8 +72,9 @@ def to_actions(dp, acts):
|
||||
tp_dst = int(a.get('tp_dst', 0))
|
||||
actions.append(dp.ofproto_parser.OFPActionSetTpDst(tp_dst))
|
||||
elif action_type == 'ENQUEUE':
|
||||
port = int(a.get('port', ofproto_v1_0.OFPP_NONE))
|
||||
queue_id = int(a.get('queue_id', 0))
|
||||
port = UTIL.ofp_port_from_user(
|
||||
a.get('port', ofproto_v1_0.OFPP_NONE))
|
||||
queue_id = UTIL.ofp_queue_from_user(a.get('queue_id', 0))
|
||||
actions.append(dp.ofproto_parser.OFPActionEnqueue(port, queue_id))
|
||||
else:
|
||||
LOG.error('Unknown action type')
|
||||
@ -83,7 +88,8 @@ def actions_to_str(acts):
|
||||
action_type = a.cls_action_type
|
||||
|
||||
if action_type == ofproto_v1_0.OFPAT_OUTPUT:
|
||||
buf = 'OUTPUT:' + str(a.port)
|
||||
port = UTIL.ofp_port_to_user(a.port)
|
||||
buf = 'OUTPUT:' + str(port)
|
||||
elif action_type == ofproto_v1_0.OFPAT_SET_VLAN_VID:
|
||||
buf = 'SET_VLAN_VID:' + str(a.vlan_vid)
|
||||
elif action_type == ofproto_v1_0.OFPAT_SET_VLAN_PCP:
|
||||
@ -107,7 +113,9 @@ def actions_to_str(acts):
|
||||
elif action_type == ofproto_v1_0.OFPAT_SET_TP_DST:
|
||||
buf = 'SET_TP_DST:' + str(a.tp)
|
||||
elif action_type == ofproto_v1_0.OFPAT_ENQUEUE:
|
||||
buf = 'ENQUEUE:' + str(a.port) + ":" + str(a.queue_id)
|
||||
port = UTIL.ofp_port_to_user(a.port)
|
||||
queue = UTIL.ofp_queue_to_user(a.queue_id)
|
||||
buf = 'ENQUEUE:' + str(port) + ":" + str(queue)
|
||||
elif action_type == ofproto_v1_0.OFPAT_VENDOR:
|
||||
buf = 'VENDOR'
|
||||
else:
|
||||
@ -146,7 +154,7 @@ def to_match(dp, attrs):
|
||||
|
||||
for key, value in attrs.items():
|
||||
if key == 'in_port':
|
||||
in_port = int(value)
|
||||
in_port = UTIL.ofp_port_from_user(value)
|
||||
wildcards &= ~ofp.OFPFW_IN_PORT
|
||||
elif key == 'dl_src':
|
||||
dl_src = haddr_to_bin(value)
|
||||
@ -210,7 +218,7 @@ def match_to_str(m):
|
||||
match = {}
|
||||
|
||||
if ~m.wildcards & ofproto_v1_0.OFPFW_IN_PORT:
|
||||
match['in_port'] = m.in_port
|
||||
match['in_port'] = UTIL.ofp_port_to_user(m.in_port)
|
||||
|
||||
if ~m.wildcards & ofproto_v1_0.OFPFW_DL_SRC:
|
||||
match['dl_src'] = haddr_to_str(m.dl_src)
|
||||
@ -328,8 +336,10 @@ def get_queue_stats(dp, waiters):
|
||||
def get_flow_stats(dp, waiters, flow=None):
|
||||
flow = flow if flow else {}
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
table_id = int(flow.get('table_id', 0xff))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_NONE))
|
||||
table_id = UTIL.ofp_table_from_user(
|
||||
flow.get('table_id', 0xff))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_NONE))
|
||||
|
||||
stats = dp.ofproto_parser.OFPFlowStatsRequest(
|
||||
dp, 0, match, table_id, out_port)
|
||||
@ -353,7 +363,7 @@ def get_flow_stats(dp, waiters, flow=None):
|
||||
'duration_sec': stats.duration_sec,
|
||||
'duration_nsec': stats.duration_nsec,
|
||||
'packet_count': stats.packet_count,
|
||||
'table_id': stats.table_id}
|
||||
'table_id': UTIL.ofp_table_to_user(stats.table_id)}
|
||||
flows.append(s)
|
||||
flows = {str(dp.id): flows}
|
||||
return flows
|
||||
@ -362,8 +372,10 @@ def get_flow_stats(dp, waiters, flow=None):
|
||||
def get_aggregate_flow_stats(dp, waiters, flow=None):
|
||||
flow = flow if flow else {}
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
table_id = int(flow.get('table_id', 0xff))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_NONE))
|
||||
table_id = UTIL.ofp_table_from_user(
|
||||
flow.get('table_id', 0xff))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_NONE))
|
||||
|
||||
stats = dp.ofproto_parser.OFPAggregateStatsRequest(
|
||||
dp, 0, match, table_id, out_port)
|
||||
@ -422,7 +434,7 @@ def get_table_stats(dp, waiters):
|
||||
for k, v in match_convert.items():
|
||||
if (1 << k) & stat.wildcards:
|
||||
wildcards.append(v)
|
||||
s = {'table_id': stat.table_id,
|
||||
s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
|
||||
'name': stat.name.decode('utf-8'),
|
||||
'wildcards': wildcards,
|
||||
'max_entries': stat.max_entries,
|
||||
@ -444,7 +456,7 @@ def get_port_stats(dp, waiters):
|
||||
ports = []
|
||||
for msg in msgs:
|
||||
for stats in msg.body:
|
||||
s = {'port_no': stats.port_no,
|
||||
s = {'port_no': UTIL.ofp_port_to_user(stats.port_no),
|
||||
'rx_packets': stats.rx_packets,
|
||||
'tx_packets': stats.tx_packets,
|
||||
'rx_bytes': stats.rx_bytes,
|
||||
@ -473,7 +485,7 @@ def get_port_desc(dp, waiters):
|
||||
for msg in msgs:
|
||||
stats = msg.ports
|
||||
for stat in stats.values():
|
||||
d = {'port_no': stat.port_no,
|
||||
d = {'port_no': UTIL.ofp_port_to_user(stat.port_no),
|
||||
'hw_addr': stat.hw_addr,
|
||||
'name': stat.name.decode('utf-8'),
|
||||
'config': stat.config,
|
||||
@ -491,8 +503,10 @@ def mod_flow_entry(dp, flow, cmd):
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
priority = int(flow.get('priority',
|
||||
dp.ofproto.OFP_DEFAULT_PRIORITY))
|
||||
buffer_id = int(flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_NONE))
|
||||
buffer_id = UTIL.ofp_buffer_from_user(
|
||||
flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_NONE))
|
||||
flags = int(flow.get('flags', 0))
|
||||
idle_timeout = int(flow.get('idle_timeout', 0))
|
||||
hard_timeout = int(flow.get('hard_timeout', 0))
|
||||
@ -522,7 +536,7 @@ def delete_flow_entry(dp):
|
||||
|
||||
|
||||
def mod_port_behavior(dp, port_config):
|
||||
port_no = int(port_config.get('port_no', 0))
|
||||
port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
|
||||
hw_addr = str(port_config.get('hw_addr'))
|
||||
config = int(port_config.get('config', 0))
|
||||
mask = int(port_config.get('mask', 0))
|
||||
|
||||
@ -22,22 +22,14 @@ from ryu.ofproto import inet
|
||||
from ryu.ofproto import ofproto_v1_2
|
||||
from ryu.ofproto import ofproto_v1_2_parser
|
||||
from ryu.lib import hub
|
||||
from ryu.lib import ofctl_utils
|
||||
|
||||
|
||||
LOG = logging.getLogger('ryu.lib.ofctl_v1_2')
|
||||
|
||||
DEFAULT_TIMEOUT = 1.0
|
||||
|
||||
|
||||
def str_to_int(src):
|
||||
if isinstance(src, str):
|
||||
if src.startswith("0x") or src.startswith("0X"):
|
||||
dst = int(src, 16)
|
||||
else:
|
||||
dst = int(src)
|
||||
else:
|
||||
dst = src
|
||||
return dst
|
||||
UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_2)
|
||||
|
||||
|
||||
def to_action(dp, dic):
|
||||
@ -46,8 +38,8 @@ def to_action(dp, dic):
|
||||
|
||||
action_type = dic.get('type')
|
||||
if action_type == 'OUTPUT':
|
||||
out_port = int(dic.get('port', ofp.OFPP_ANY))
|
||||
max_len = int(dic.get('max_len', ofp.OFPCML_MAX))
|
||||
out_port = UTIL.ofp_port_from_user(dic.get('port', ofp.OFPP_ANY))
|
||||
max_len = UTIL.ofp_cml_from_user(dic.get('max_len', ofp.OFPCML_MAX))
|
||||
result = parser.OFPActionOutput(out_port, max_len)
|
||||
elif action_type == 'COPY_TTL_OUT':
|
||||
result = parser.OFPActionCopyTtlOut()
|
||||
@ -70,10 +62,10 @@ def to_action(dp, dic):
|
||||
ethertype = int(dic.get('ethertype'))
|
||||
result = parser.OFPActionPopMpls(ethertype)
|
||||
elif action_type == 'SET_QUEUE':
|
||||
queue_id = int(dic.get('queue_id'))
|
||||
queue_id = UTIL.ofp_queue_from_user(dic.get('queue_id'))
|
||||
result = parser.OFPActionSetQueue(queue_id)
|
||||
elif action_type == 'GROUP':
|
||||
group_id = int(dic.get('group_id'))
|
||||
group_id = UTIL.ofp_group_from_user(dic.get('group_id'))
|
||||
result = parser.OFPActionGroup(group_id)
|
||||
elif action_type == 'SET_NW_TTL':
|
||||
nw_ttl = int(dic.get('nw_ttl'))
|
||||
@ -118,11 +110,11 @@ def to_actions(dp, acts):
|
||||
inst.append(parser.OFPInstructionActions(
|
||||
ofp.OFPIT_CLEAR_ACTIONS, []))
|
||||
elif action_type == 'GOTO_TABLE':
|
||||
table_id = int(a.get('table_id'))
|
||||
table_id = UTIL.ofp_table_from_user(a.get('table_id'))
|
||||
inst.append(parser.OFPInstructionGotoTable(table_id))
|
||||
elif action_type == 'WRITE_METADATA':
|
||||
metadata = str_to_int(a.get('metadata'))
|
||||
metadata_mask = (str_to_int(a['metadata_mask'])
|
||||
metadata = ofctl_utils.str_to_int(a.get('metadata'))
|
||||
metadata_mask = (ofctl_utils.str_to_int(a['metadata_mask'])
|
||||
if 'metadata_mask' in a
|
||||
else parser.UINT64_MAX)
|
||||
inst.append(
|
||||
@ -141,7 +133,8 @@ def action_to_str(act):
|
||||
action_type = act.cls_action_type
|
||||
|
||||
if action_type == ofproto_v1_2.OFPAT_OUTPUT:
|
||||
buf = 'OUTPUT:' + str(act.port)
|
||||
port = UTIL.ofp_port_to_user(act.port)
|
||||
buf = 'OUTPUT:' + str(port)
|
||||
elif action_type == ofproto_v1_2.OFPAT_COPY_TTL_OUT:
|
||||
buf = 'COPY_TTL_OUT'
|
||||
elif action_type == ofproto_v1_2.OFPAT_COPY_TTL_IN:
|
||||
@ -159,9 +152,11 @@ def action_to_str(act):
|
||||
elif action_type == ofproto_v1_2.OFPAT_POP_MPLS:
|
||||
buf = 'POP_MPLS:' + str(act.ethertype)
|
||||
elif action_type == ofproto_v1_2.OFPAT_SET_QUEUE:
|
||||
buf = 'SET_QUEUE:' + str(act.queue_id)
|
||||
queue_id = UTIL.ofp_queue_to_user(act.queue_id)
|
||||
buf = 'SET_QUEUE:' + str(queue_id)
|
||||
elif action_type == ofproto_v1_2.OFPAT_GROUP:
|
||||
buf = 'GROUP:' + str(act.group_id)
|
||||
group_id = UTIL.ofp_group_to_user(act.group_id)
|
||||
buf = 'GROUP:' + str(group_id)
|
||||
elif action_type == ofproto_v1_2.OFPAT_SET_NW_TTL:
|
||||
buf = 'SET_NW_TTL:' + str(act.nw_ttl)
|
||||
elif action_type == ofproto_v1_2.OFPAT_DEC_NW_TTL:
|
||||
@ -194,7 +189,8 @@ def actions_to_str(instructions):
|
||||
actions.append('UNKNOWN')
|
||||
elif isinstance(instruction,
|
||||
ofproto_v1_2_parser.OFPInstructionGotoTable):
|
||||
buf = 'GOTO_TABLE:' + str(instruction.table_id)
|
||||
table_id = UTIL.ofp_table_to_user(instruction.table_id)
|
||||
buf = 'GOTO_TABLE:' + str(table_id)
|
||||
actions.append(buf)
|
||||
|
||||
elif isinstance(instruction,
|
||||
@ -212,7 +208,7 @@ def actions_to_str(instructions):
|
||||
|
||||
|
||||
def to_match(dp, attrs):
|
||||
convert = {'in_port': int,
|
||||
convert = {'in_port': UTIL.ofp_port_from_user,
|
||||
'in_phy_port': int,
|
||||
'metadata': to_match_masked_int,
|
||||
'dl_dst': to_match_eth,
|
||||
@ -345,9 +341,10 @@ def to_match_vid(value):
|
||||
def to_match_masked_int(value):
|
||||
if isinstance(value, str) and '/' in value:
|
||||
value = value.split('/')
|
||||
return str_to_int(value[0]), str_to_int(value[1])
|
||||
return (ofctl_utils.str_to_int(value[0]),
|
||||
ofctl_utils.str_to_int(value[1]))
|
||||
else:
|
||||
return str_to_int(value)
|
||||
return ofctl_utils.str_to_int(value)
|
||||
|
||||
|
||||
def match_to_str(ofmatch):
|
||||
@ -377,6 +374,8 @@ def match_to_str(ofmatch):
|
||||
value = match_field['OXMTlv']['value']
|
||||
if key == 'dl_vlan':
|
||||
value = match_vid_to_str(value, mask)
|
||||
elif key == 'in_port':
|
||||
value = UTIL.ofp_port_to_user(value)
|
||||
else:
|
||||
if mask is not None:
|
||||
value = str(value) + '/' + str(mask)
|
||||
@ -455,6 +454,7 @@ def get_queue_stats(dp, waiters):
|
||||
|
||||
def get_queue_config(dp, port, waiters):
|
||||
ofp = dp.ofproto
|
||||
port = UTIL.ofp_port_from_user(port)
|
||||
stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
|
||||
msgs = []
|
||||
send_stats_request(dp, stats, waiters, msgs)
|
||||
@ -478,11 +478,11 @@ def get_queue_config(dp, port, waiters):
|
||||
p['experimenter'] = prop.experimenter
|
||||
p['data'] = prop.data
|
||||
prop_list.append(p)
|
||||
q = {'port': queue.port,
|
||||
q = {'port': UTIL.ofp_port_to_user(queue.port),
|
||||
'properties': prop_list,
|
||||
'queue_id': queue.queue_id}
|
||||
'queue_id': UTIL.ofp_queue_to_user(queue.queue_id)}
|
||||
queue_list.append(q)
|
||||
c = {'port': config.port,
|
||||
c = {'port': UTIL.ofp_port_to_user(config.port),
|
||||
'queues': queue_list}
|
||||
configs.append(c)
|
||||
configs = {str(dp.id): configs}
|
||||
@ -492,9 +492,12 @@ def get_queue_config(dp, port, waiters):
|
||||
|
||||
def get_flow_stats(dp, waiters, flow=None):
|
||||
flow = flow if flow else {}
|
||||
table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
table_id = UTIL.ofp_table_from_user(
|
||||
flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = UTIL.ofp_group_from_user(
|
||||
flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
cookie_mask = int(flow.get('cookie_mask', 0))
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
@ -520,7 +523,7 @@ def get_flow_stats(dp, waiters, flow=None):
|
||||
'duration_sec': stats.duration_sec,
|
||||
'duration_nsec': stats.duration_nsec,
|
||||
'packet_count': stats.packet_count,
|
||||
'table_id': stats.table_id,
|
||||
'table_id': UTIL.ofp_table_to_user(stats.table_id),
|
||||
'length': stats.length}
|
||||
flows.append(s)
|
||||
flows = {str(dp.id): flows}
|
||||
@ -530,9 +533,12 @@ def get_flow_stats(dp, waiters, flow=None):
|
||||
|
||||
def get_aggregate_flow_stats(dp, waiters, flow=None):
|
||||
flow = flow if flow else {}
|
||||
table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
table_id = UTIL.ofp_table_from_user(
|
||||
flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = UTIL.ofp_group_from_user(
|
||||
flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
cookie_mask = int(flow.get('cookie_mask', 0))
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
@ -658,7 +664,7 @@ def get_table_stats(dp, waiters):
|
||||
for k, v in table_conf_convert.items():
|
||||
if (1 << k) & stat.config:
|
||||
config.append(v)
|
||||
s = {'table_id': stat.table_id,
|
||||
s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
|
||||
'name': stat.name.decode('utf-8'),
|
||||
'match': match,
|
||||
'wildcards': wildcards,
|
||||
@ -689,7 +695,7 @@ def get_port_stats(dp, waiters):
|
||||
ports = []
|
||||
for msg in msgs:
|
||||
for stats in msg.body:
|
||||
s = {'port_no': stats.port_no,
|
||||
s = {'port_no': UTIL.ofp_port_to_user(stats.port_no),
|
||||
'rx_packets': stats.rx_packets,
|
||||
'tx_packets': stats.tx_packets,
|
||||
'rx_bytes': stats.rx_bytes,
|
||||
@ -722,7 +728,7 @@ def get_group_stats(dp, waiters):
|
||||
'byte_count': bucket_counter.byte_count}
|
||||
bucket_counters.append(c)
|
||||
g = {'length': stats.length,
|
||||
'group_id': stats.group_id,
|
||||
'group_id': UTIL.ofp_group_to_user(stats.group_id),
|
||||
'ref_count': stats.ref_count,
|
||||
'packet_count': stats.packet_count,
|
||||
'byte_count': stats.byte_count,
|
||||
@ -817,7 +823,7 @@ def get_group_desc(dp, waiters):
|
||||
'actions': actions}
|
||||
buckets.append(b)
|
||||
d = {'type': type_convert.get(stats.type),
|
||||
'group_id': stats.group_id,
|
||||
'group_id': UTIL.ofp_group_to_user(stats.group_id),
|
||||
'buckets': buckets}
|
||||
descs.append(d)
|
||||
descs = {str(dp.id): descs}
|
||||
@ -835,7 +841,7 @@ def get_port_desc(dp, waiters):
|
||||
for msg in msgs:
|
||||
stats = msg.ports
|
||||
for stat in stats.values():
|
||||
d = {'port_no': stat.port_no,
|
||||
d = {'port_no': UTIL.ofp_port_to_user(stat.port_no),
|
||||
'hw_addr': stat.hw_addr,
|
||||
'name': stat.name.decode('utf-8'),
|
||||
'config': stat.config,
|
||||
@ -854,13 +860,16 @@ def get_port_desc(dp, waiters):
|
||||
def mod_flow_entry(dp, flow, cmd):
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
cookie_mask = int(flow.get('cookie_mask', 0))
|
||||
table_id = int(flow.get('table_id', 0))
|
||||
table_id = UTIL.ofp_table_from_user(flow.get('table_id', 0))
|
||||
idle_timeout = int(flow.get('idle_timeout', 0))
|
||||
hard_timeout = int(flow.get('hard_timeout', 0))
|
||||
priority = int(flow.get('priority', 0))
|
||||
buffer_id = int(flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
buffer_id = UTIL.ofp_buffer_from_user(
|
||||
flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = UTIL.ofp_group_from_user(
|
||||
flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
flags = int(flow.get('flags', 0))
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
inst = to_actions(dp, flow.get('actions', []))
|
||||
@ -884,7 +893,7 @@ def mod_group_entry(dp, group, cmd):
|
||||
if type_ is None:
|
||||
LOG.error('Unknown group type: %s', group.get('type'))
|
||||
|
||||
group_id = int(group.get('group_id', 0))
|
||||
group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
|
||||
|
||||
buckets = []
|
||||
for bucket in group.get('buckets', []):
|
||||
@ -906,7 +915,7 @@ def mod_group_entry(dp, group, cmd):
|
||||
|
||||
|
||||
def mod_port_behavior(dp, port_config):
|
||||
port_no = int(port_config.get('port_no', 0))
|
||||
port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
|
||||
hw_addr = str(port_config.get('hw_addr'))
|
||||
config = int(port_config.get('config', 0))
|
||||
mask = int(port_config.get('mask', 0))
|
||||
|
||||
@ -22,22 +22,14 @@ from ryu.ofproto import inet
|
||||
from ryu.ofproto import ofproto_v1_3
|
||||
from ryu.ofproto import ofproto_v1_3_parser
|
||||
from ryu.lib import hub
|
||||
from ryu.lib import ofctl_utils
|
||||
|
||||
|
||||
LOG = logging.getLogger('ryu.lib.ofctl_v1_3')
|
||||
|
||||
DEFAULT_TIMEOUT = 1.0
|
||||
|
||||
|
||||
def str_to_int(src):
|
||||
if isinstance(src, str):
|
||||
if src.startswith("0x") or src.startswith("0X"):
|
||||
dst = int(src, 16)
|
||||
else:
|
||||
dst = int(src)
|
||||
else:
|
||||
dst = src
|
||||
return dst
|
||||
UTIL = ofctl_utils.OFCtlUtil(ofproto_v1_3)
|
||||
|
||||
|
||||
def to_action(dp, dic):
|
||||
@ -46,8 +38,8 @@ def to_action(dp, dic):
|
||||
|
||||
action_type = dic.get('type')
|
||||
if action_type == 'OUTPUT':
|
||||
out_port = int(dic.get('port', ofp.OFPP_ANY))
|
||||
max_len = int(dic.get('max_len', ofp.OFPCML_MAX))
|
||||
out_port = UTIL.ofp_port_from_user(dic.get('port', ofp.OFPP_ANY))
|
||||
max_len = UTIL.ofp_cml_from_user(dic.get('max_len', ofp.OFPCML_MAX))
|
||||
result = parser.OFPActionOutput(out_port, max_len)
|
||||
elif action_type == 'COPY_TTL_OUT':
|
||||
result = parser.OFPActionCopyTtlOut()
|
||||
@ -70,10 +62,10 @@ def to_action(dp, dic):
|
||||
ethertype = int(dic.get('ethertype'))
|
||||
result = parser.OFPActionPopMpls(ethertype)
|
||||
elif action_type == 'SET_QUEUE':
|
||||
queue_id = int(dic.get('queue_id'))
|
||||
queue_id = UTIL.ofp_queue_from_user(dic.get('queue_id'))
|
||||
result = parser.OFPActionSetQueue(queue_id)
|
||||
elif action_type == 'GROUP':
|
||||
group_id = int(dic.get('group_id'))
|
||||
group_id = UTIL.ofp_group_from_user(dic.get('group_id'))
|
||||
result = parser.OFPActionGroup(group_id)
|
||||
elif action_type == 'SET_NW_TTL':
|
||||
nw_ttl = int(dic.get('nw_ttl'))
|
||||
@ -124,18 +116,18 @@ def to_actions(dp, acts):
|
||||
inst.append(parser.OFPInstructionActions(
|
||||
ofp.OFPIT_CLEAR_ACTIONS, []))
|
||||
elif action_type == 'GOTO_TABLE':
|
||||
table_id = int(a.get('table_id'))
|
||||
table_id = UTIL.ofp_table_from_user(a.get('table_id'))
|
||||
inst.append(parser.OFPInstructionGotoTable(table_id))
|
||||
elif action_type == 'WRITE_METADATA':
|
||||
metadata = str_to_int(a.get('metadata'))
|
||||
metadata_mask = (str_to_int(a['metadata_mask'])
|
||||
metadata = ofctl_utils.str_to_int(a.get('metadata'))
|
||||
metadata_mask = (ofctl_utils.str_to_int(a['metadata_mask'])
|
||||
if 'metadata_mask' in a
|
||||
else parser.UINT64_MAX)
|
||||
inst.append(
|
||||
parser.OFPInstructionWriteMetadata(
|
||||
metadata, metadata_mask))
|
||||
elif action_type == 'METER':
|
||||
meter_id = int(a.get('meter_id'))
|
||||
meter_id = UTIL.ofp_meter_from_user(a.get('meter_id'))
|
||||
inst.append(parser.OFPInstructionMeter(meter_id))
|
||||
else:
|
||||
LOG.error('Unknown action type: %s', action_type)
|
||||
@ -150,7 +142,8 @@ def action_to_str(act):
|
||||
action_type = act.cls_action_type
|
||||
|
||||
if action_type == ofproto_v1_3.OFPAT_OUTPUT:
|
||||
buf = 'OUTPUT:' + str(act.port)
|
||||
port = UTIL.ofp_port_to_user(act.port)
|
||||
buf = 'OUTPUT:' + str(port)
|
||||
elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_OUT:
|
||||
buf = 'COPY_TTL_OUT'
|
||||
elif action_type == ofproto_v1_3.OFPAT_COPY_TTL_IN:
|
||||
@ -168,9 +161,11 @@ def action_to_str(act):
|
||||
elif action_type == ofproto_v1_3.OFPAT_POP_MPLS:
|
||||
buf = 'POP_MPLS:' + str(act.ethertype)
|
||||
elif action_type == ofproto_v1_3.OFPAT_SET_QUEUE:
|
||||
buf = 'SET_QUEUE:' + str(act.queue_id)
|
||||
queue_id = UTIL.ofp_queue_to_user(act.queue_id)
|
||||
buf = 'SET_QUEUE:' + str(queue_id)
|
||||
elif action_type == ofproto_v1_3.OFPAT_GROUP:
|
||||
buf = 'GROUP:' + str(act.group_id)
|
||||
group_id = UTIL.ofp_group_to_user(act.group_id)
|
||||
buf = 'GROUP:' + str(group_id)
|
||||
elif action_type == ofproto_v1_3.OFPAT_SET_NW_TTL:
|
||||
buf = 'SET_NW_TTL:' + str(act.nw_ttl)
|
||||
elif action_type == ofproto_v1_3.OFPAT_DEC_NW_TTL:
|
||||
@ -207,7 +202,8 @@ def actions_to_str(instructions):
|
||||
actions.append('UNKNOWN')
|
||||
elif isinstance(instruction,
|
||||
ofproto_v1_3_parser.OFPInstructionGotoTable):
|
||||
buf = 'GOTO_TABLE:' + str(instruction.table_id)
|
||||
table_id = UTIL.ofp_table_to_user(instruction.table_id)
|
||||
buf = 'GOTO_TABLE:' + str(table_id)
|
||||
actions.append(buf)
|
||||
|
||||
elif isinstance(instruction,
|
||||
@ -220,7 +216,8 @@ def actions_to_str(instructions):
|
||||
|
||||
elif isinstance(instruction,
|
||||
ofproto_v1_3_parser.OFPInstructionMeter):
|
||||
buf = 'METER:' + str(instruction.meter_id)
|
||||
meter_id = UTIL.ofp_meter_to_user(instruction.meter_id)
|
||||
buf = 'METER:' + str(meter_id)
|
||||
actions.append(buf)
|
||||
|
||||
else:
|
||||
@ -230,7 +227,7 @@ def actions_to_str(instructions):
|
||||
|
||||
|
||||
def to_match(dp, attrs):
|
||||
convert = {'in_port': int,
|
||||
convert = {'in_port': UTIL.ofp_port_from_user,
|
||||
'in_phy_port': int,
|
||||
'metadata': to_match_masked_int,
|
||||
'dl_dst': to_match_eth,
|
||||
@ -367,9 +364,10 @@ def to_match_vid(value):
|
||||
def to_match_masked_int(value):
|
||||
if isinstance(value, str) and '/' in value:
|
||||
value = value.split('/')
|
||||
return str_to_int(value[0]), str_to_int(value[1])
|
||||
return (ofctl_utils.str_to_int(value[0]),
|
||||
ofctl_utils.str_to_int(value[1]))
|
||||
else:
|
||||
return str_to_int(value)
|
||||
return ofctl_utils.str_to_int(value)
|
||||
|
||||
|
||||
def match_to_str(ofmatch):
|
||||
@ -400,6 +398,8 @@ def match_to_str(ofmatch):
|
||||
value = match_field['OXMTlv']['value']
|
||||
if key == 'dl_vlan':
|
||||
value = match_vid_to_str(value, mask)
|
||||
elif key == 'in_port':
|
||||
value = UTIL.ofp_port_to_user(value)
|
||||
else:
|
||||
if mask is not None:
|
||||
value = str(value) + '/' + str(mask)
|
||||
@ -480,6 +480,7 @@ def get_queue_stats(dp, waiters):
|
||||
|
||||
def get_queue_config(dp, port, waiters):
|
||||
ofp = dp.ofproto
|
||||
port = UTIL.ofp_port_from_user(port)
|
||||
stats = dp.ofproto_parser.OFPQueueGetConfigRequest(dp, port)
|
||||
msgs = []
|
||||
send_stats_request(dp, stats, waiters, msgs)
|
||||
@ -503,11 +504,11 @@ def get_queue_config(dp, port, waiters):
|
||||
p['experimenter'] = prop.experimenter
|
||||
p['data'] = prop.data
|
||||
prop_list.append(p)
|
||||
q = {'port': queue.port,
|
||||
q = {'port': UTIL.ofp_port_to_user(queue.port),
|
||||
'properties': prop_list,
|
||||
'queue_id': queue.queue_id}
|
||||
'queue_id': UTIL.ofp_queue_to_user(queue.queue_id)}
|
||||
queue_list.append(q)
|
||||
c = {'port': config.port,
|
||||
c = {'port': UTIL.ofp_port_to_user(config.port),
|
||||
'queues': queue_list}
|
||||
configs.append(c)
|
||||
configs = {str(dp.id): configs}
|
||||
@ -517,10 +518,13 @@ def get_queue_config(dp, port, waiters):
|
||||
|
||||
def get_flow_stats(dp, waiters, flow=None):
|
||||
flow = flow if flow else {}
|
||||
table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
table_id = UTIL.ofp_table_from_user(
|
||||
flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
flags = int(flow.get('flags', 0))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = UTIL.ofp_group_from_user(
|
||||
flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
cookie_mask = int(flow.get('cookie_mask', 0))
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
@ -548,7 +552,7 @@ def get_flow_stats(dp, waiters, flow=None):
|
||||
'duration_sec': stats.duration_sec,
|
||||
'duration_nsec': stats.duration_nsec,
|
||||
'packet_count': stats.packet_count,
|
||||
'table_id': stats.table_id,
|
||||
'table_id': UTIL.ofp_table_to_user(stats.table_id),
|
||||
'length': stats.length,
|
||||
'flags': stats.flags}
|
||||
flows.append(s)
|
||||
@ -559,10 +563,13 @@ def get_flow_stats(dp, waiters, flow=None):
|
||||
|
||||
def get_aggregate_flow_stats(dp, waiters, flow=None):
|
||||
flow = flow if flow else {}
|
||||
table_id = int(flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
table_id = UTIL.ofp_table_from_user(
|
||||
flow.get('table_id', dp.ofproto.OFPTT_ALL))
|
||||
flags = int(flow.get('flags', 0))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = UTIL.ofp_group_from_user(
|
||||
flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
cookie_mask = int(flow.get('cookie_mask', 0))
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
@ -595,7 +602,7 @@ def get_table_stats(dp, waiters):
|
||||
for msg in msgs:
|
||||
stats = msg.body
|
||||
for stat in stats:
|
||||
s = {'table_id': stat.table_id,
|
||||
s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
|
||||
'active_count': stat.active_count,
|
||||
'lookup_count': stat.lookup_count,
|
||||
'matched_count': stat.matched_count}
|
||||
@ -687,7 +694,7 @@ def get_table_features(dp, waiters):
|
||||
elif prop.type in p_type_experimenter:
|
||||
pass
|
||||
properties.append(p)
|
||||
s = {'table_id': stat.table_id,
|
||||
s = {'table_id': UTIL.ofp_table_to_user(stat.table_id),
|
||||
'name': stat.name.decode('utf-8'),
|
||||
'metadata_match': stat.metadata_match,
|
||||
'metadata_write': stat.metadata_write,
|
||||
@ -710,7 +717,7 @@ def get_port_stats(dp, waiters):
|
||||
ports = []
|
||||
for msg in msgs:
|
||||
for stats in msg.body:
|
||||
s = {'port_no': stats.port_no,
|
||||
s = {'port_no': UTIL.ofp_port_to_user(stats.port_no),
|
||||
'rx_packets': stats.rx_packets,
|
||||
'tx_packets': stats.tx_packets,
|
||||
'rx_bytes': stats.rx_bytes,
|
||||
@ -744,7 +751,7 @@ def get_meter_stats(dp, waiters):
|
||||
b = {'packet_band_count': band.packet_band_count,
|
||||
'byte_band_count': band.byte_band_count}
|
||||
bands.append(b)
|
||||
s = {'meter_id': stats.meter_id,
|
||||
s = {'meter_id': UTIL.ofp_meter_to_user(stats.meter_id),
|
||||
'len': stats.len,
|
||||
'flow_count': stats.flow_count,
|
||||
'packet_in_count': stats.packet_in_count,
|
||||
@ -826,7 +833,7 @@ def get_meter_config(dp, waiters):
|
||||
if k & config.flags:
|
||||
c_flags.append(v)
|
||||
c = {'flags': c_flags,
|
||||
'meter_id': config.meter_id,
|
||||
'meter_id': UTIL.ofp_meter_to_user(config.meter_id),
|
||||
'bands': bands}
|
||||
configs.append(c)
|
||||
configs = {str(dp.id): configs}
|
||||
@ -848,7 +855,7 @@ def get_group_stats(dp, waiters):
|
||||
'byte_count': bucket_stat.byte_count}
|
||||
bucket_stats.append(c)
|
||||
g = {'length': stats.length,
|
||||
'group_id': stats.group_id,
|
||||
'group_id': UTIL.ofp_group_to_user(stats.group_id),
|
||||
'ref_count': stats.ref_count,
|
||||
'packet_count': stats.packet_count,
|
||||
'byte_count': stats.byte_count,
|
||||
@ -947,7 +954,7 @@ def get_group_desc(dp, waiters):
|
||||
'actions': actions}
|
||||
buckets.append(b)
|
||||
d = {'type': type_convert.get(stats.type),
|
||||
'group_id': stats.group_id,
|
||||
'group_id': UTIL.ofp_group_to_user(stats.group_id),
|
||||
'buckets': buckets}
|
||||
descs.append(d)
|
||||
descs = {str(dp.id): descs}
|
||||
@ -965,7 +972,7 @@ def get_port_desc(dp, waiters):
|
||||
for msg in msgs:
|
||||
stats = msg.body
|
||||
for stat in stats:
|
||||
d = {'port_no': stat.port_no,
|
||||
d = {'port_no': UTIL.ofp_port_to_user(stat.port_no),
|
||||
'hw_addr': stat.hw_addr,
|
||||
'name': stat.name.decode('utf-8'),
|
||||
'config': stat.config,
|
||||
@ -984,13 +991,16 @@ def get_port_desc(dp, waiters):
|
||||
def mod_flow_entry(dp, flow, cmd):
|
||||
cookie = int(flow.get('cookie', 0))
|
||||
cookie_mask = int(flow.get('cookie_mask', 0))
|
||||
table_id = int(flow.get('table_id', 0))
|
||||
table_id = UTIL.ofp_table_from_user(flow.get('table_id', 0))
|
||||
idle_timeout = int(flow.get('idle_timeout', 0))
|
||||
hard_timeout = int(flow.get('hard_timeout', 0))
|
||||
priority = int(flow.get('priority', 0))
|
||||
buffer_id = int(flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
||||
out_port = int(flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = int(flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
buffer_id = UTIL.ofp_buffer_from_user(
|
||||
flow.get('buffer_id', dp.ofproto.OFP_NO_BUFFER))
|
||||
out_port = UTIL.ofp_port_from_user(
|
||||
flow.get('out_port', dp.ofproto.OFPP_ANY))
|
||||
out_group = UTIL.ofp_group_from_user(
|
||||
flow.get('out_group', dp.ofproto.OFPG_ANY))
|
||||
flags = int(flow.get('flags', 0))
|
||||
match = to_match(dp, flow.get('match', {}))
|
||||
inst = to_actions(dp, flow.get('actions', []))
|
||||
@ -1021,7 +1031,7 @@ def mod_meter_entry(dp, meter, cmd):
|
||||
continue
|
||||
flags |= flags_convert.get(flag)
|
||||
|
||||
meter_id = int(meter.get('meter_id', 0))
|
||||
meter_id = UTIL.ofp_meter_from_user(meter.get('meter_id', 0))
|
||||
|
||||
bands = []
|
||||
for band in meter.get('bands', []):
|
||||
@ -1061,7 +1071,7 @@ def mod_group_entry(dp, group, cmd):
|
||||
if type_ is None:
|
||||
LOG.error('Unknown group type: %s', group.get('type'))
|
||||
|
||||
group_id = int(group.get('group_id', 0))
|
||||
group_id = UTIL.ofp_group_from_user(group.get('group_id', 0))
|
||||
|
||||
buckets = []
|
||||
for bucket in group.get('buckets', []):
|
||||
@ -1083,7 +1093,7 @@ def mod_group_entry(dp, group, cmd):
|
||||
|
||||
|
||||
def mod_port_behavior(dp, port_config):
|
||||
port_no = int(port_config.get('port_no', 0))
|
||||
port_no = UTIL.ofp_port_from_user(port_config.get('port_no', 0))
|
||||
hw_addr = str(port_config.get('hw_addr'))
|
||||
config = int(port_config.get('config', 0))
|
||||
mask = int(port_config.get('mask', 0))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user