mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-01-23 01:21:31 +01:00
ofctl_v1_2/3: Fully support the match combinations for VLAN ID
Currently, when VLAN ID match field is specified,
ofctl_v1_[23] is compatible with only match combination 1) of
the following three match combinations.
This patch makes it possible to set the all three combinations.
Match combinations for VLAN ID :
1) To match only packets with VLAN tag and VID equal value
2) To match only packets without a VLAN tag
3) To match only packets with a VLAN tag regardless of its value
In order to set the match combinations 2) or 3), please describe
"dl_vlan" field as hexadecimal string value like as follows.
Before applying this patch:
{"dl_vlan": 3 } # int
After applying this patch:
{"dl_vlan": 3 } # int (same as before applying)
{"dl_vlan": "0x0000"} # hexadecimal string without mask
{"dl_vlan": "0x1000/0x1000"} # hexadecimal string with mask
NOTE: When "dl_vlan" field is described as decimal int value,
OFPVID_PRESENT(0x1000) bit is automatically applied.
OTOH, OFPVID_PRESENT(0x1000) bit is NOT automatically applied
to hexadecimal string value.
For curl command examples, please refer to the following page in Ryu-documentation.
http://ryu.readthedocs.org/en/latest/app/ofctl_rest.html#example-of-vlan-id-match-field
Signed-off-by: Minoru TAKAHASHI <takahashi.minoru7@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
31353a95dd
commit
1979bde573
@ -198,8 +198,8 @@ def to_match(dp, attrs):
|
||||
'eth_src': to_match_eth,
|
||||
'dl_type': int,
|
||||
'eth_type': int,
|
||||
'dl_vlan': int,
|
||||
'vlan_vid': int,
|
||||
'dl_vlan': to_match_vid,
|
||||
'vlan_vid': to_match_vid,
|
||||
'vlan_pcp': int,
|
||||
'ip_dscp': int,
|
||||
'ip_ecn': int,
|
||||
@ -268,9 +268,6 @@ def to_match(dp, attrs):
|
||||
ip_proto = attrs.get('nw_proto', attrs.get('ip_proto', 0))
|
||||
key = conv[ip_proto][key]
|
||||
kwargs[key] = value
|
||||
elif key == 'vlan_vid':
|
||||
# VLAN ID
|
||||
kwargs[key] = value | ofproto_v1_2.OFPVID_PRESENT
|
||||
else:
|
||||
# others
|
||||
kwargs[key] = value
|
||||
@ -296,6 +293,28 @@ def to_match_ip(value):
|
||||
return value
|
||||
|
||||
|
||||
def to_match_vid(value):
|
||||
# NOTE: If "vlan_id/dl_vlan" field is described as decimal int value
|
||||
# (and decimal string value), it is treated as values of
|
||||
# VLAN tag, and OFPVID_PRESENT(0x1000) bit is automatically
|
||||
# applied. OTOH, If it is described as hexadecimal string,
|
||||
# treated as values of oxm_value (including OFPVID_PRESENT
|
||||
# bit), and OFPVID_PRESENT bit is NOT automatically applied.
|
||||
if isinstance(value, int):
|
||||
# described as decimal int value
|
||||
return value | ofproto_v1_2.OFPVID_PRESENT
|
||||
else:
|
||||
if '/' in value:
|
||||
val = value.split('/')
|
||||
return int(val[0], 0), int(val[1], 0)
|
||||
else:
|
||||
if value.isdigit():
|
||||
# described as decimal string value
|
||||
return int(value, 10) | ofproto_v1_2.OFPVID_PRESENT
|
||||
else:
|
||||
return int(value, 0)
|
||||
|
||||
|
||||
def to_match_metadata(value):
|
||||
if '/' in value:
|
||||
value = value.split('/')
|
||||
@ -330,9 +349,9 @@ def match_to_str(ofmatch):
|
||||
mask = match_field['OXMTlv']['mask']
|
||||
value = match_field['OXMTlv']['value']
|
||||
if key == 'dl_vlan':
|
||||
value &= ~ofproto_v1_2.OFPVID_PRESENT
|
||||
value = match_vid_to_str(value, mask)
|
||||
elif key == 'metadata':
|
||||
value = ('%d/%d' % (value, mask) if mask else '%d' % value)
|
||||
value = match_metadata_to_str(value, mask)
|
||||
else:
|
||||
if mask is not None:
|
||||
value = value + '/' + mask
|
||||
@ -343,6 +362,21 @@ def match_to_str(ofmatch):
|
||||
return match
|
||||
|
||||
|
||||
def match_metadata_to_str(value, mask):
|
||||
return ('%d/%d' % (value, mask) if mask else '%d' % value)
|
||||
|
||||
|
||||
def match_vid_to_str(value, mask):
|
||||
if mask is not None:
|
||||
value = '0x%04x/0x%04x' % (value, mask)
|
||||
else:
|
||||
if value & ofproto_v1_2.OFPVID_PRESENT:
|
||||
value = str(value & ~ofproto_v1_2.OFPVID_PRESENT)
|
||||
else:
|
||||
value = '0x%04x' % value
|
||||
return value
|
||||
|
||||
|
||||
def send_stats_request(dp, stats, waiters, msgs):
|
||||
dp.set_xid(stats)
|
||||
waiters_per_dp = waiters.setdefault(dp.id, {})
|
||||
|
||||
@ -215,8 +215,8 @@ def to_match(dp, attrs):
|
||||
'eth_src': to_match_eth,
|
||||
'dl_type': int,
|
||||
'eth_type': int,
|
||||
'dl_vlan': int,
|
||||
'vlan_vid': int,
|
||||
'dl_vlan': to_match_vid,
|
||||
'vlan_vid': to_match_vid,
|
||||
'vlan_pcp': int,
|
||||
'ip_dscp': int,
|
||||
'ip_ecn': int,
|
||||
@ -289,9 +289,6 @@ def to_match(dp, attrs):
|
||||
ip_proto = attrs.get('nw_proto', attrs.get('ip_proto', 0))
|
||||
key = conv[ip_proto][key]
|
||||
kwargs[key] = value
|
||||
elif key == 'vlan_vid':
|
||||
# VLAN ID
|
||||
kwargs[key] = value | ofproto_v1_3.OFPVID_PRESENT
|
||||
else:
|
||||
# others
|
||||
kwargs[key] = value
|
||||
@ -317,6 +314,28 @@ def to_match_ip(value):
|
||||
return value
|
||||
|
||||
|
||||
def to_match_vid(value):
|
||||
# NOTE: If "vlan_id/dl_vlan" field is described as decimal int value
|
||||
# (and decimal string value), it is treated as values of
|
||||
# VLAN tag, and OFPVID_PRESENT(0x1000) bit is automatically
|
||||
# applied. OTOH, If it is described as hexadecimal string,
|
||||
# treated as values of oxm_value (including OFPVID_PRESENT
|
||||
# bit), and OFPVID_PRESENT bit is NOT automatically applied.
|
||||
if isinstance(value, int):
|
||||
# described as decimal int value
|
||||
return value | ofproto_v1_3.OFPVID_PRESENT
|
||||
else:
|
||||
if '/' in value:
|
||||
val = value.split('/')
|
||||
return int(val[0], 0), int(val[1], 0)
|
||||
else:
|
||||
if value.isdigit():
|
||||
# described as decimal string value
|
||||
return int(value, 10) | ofproto_v1_3.OFPVID_PRESENT
|
||||
else:
|
||||
return int(value, 0)
|
||||
|
||||
|
||||
def to_match_metadata(value):
|
||||
if '/' in value:
|
||||
value = value.split('/')
|
||||
@ -352,9 +371,9 @@ def match_to_str(ofmatch):
|
||||
mask = match_field['OXMTlv']['mask']
|
||||
value = match_field['OXMTlv']['value']
|
||||
if key == 'dl_vlan':
|
||||
value &= ~ofproto_v1_3.OFPVID_PRESENT
|
||||
value = match_vid_to_str(value, mask)
|
||||
elif key == 'metadata':
|
||||
value = ('%d/%d' % (value, mask) if mask else '%d' % value)
|
||||
value = match_metadata_to_str(value, mask)
|
||||
else:
|
||||
if mask is not None:
|
||||
value = value + '/' + mask
|
||||
@ -365,6 +384,21 @@ def match_to_str(ofmatch):
|
||||
return match
|
||||
|
||||
|
||||
def match_metadata_to_str(value, mask):
|
||||
return ('%d/%d' % (value, mask) if mask else '%d' % value)
|
||||
|
||||
|
||||
def match_vid_to_str(value, mask):
|
||||
if mask is not None:
|
||||
value = '0x%04x/0x%04x' % (value, mask)
|
||||
else:
|
||||
if value & ofproto_v1_3.OFPVID_PRESENT:
|
||||
value = str(value & ~ofproto_v1_3.OFPVID_PRESENT)
|
||||
else:
|
||||
value = '0x%04x' % value
|
||||
return value
|
||||
|
||||
|
||||
def send_stats_request(dp, stats, waiters, msgs):
|
||||
dp.set_xid(stats)
|
||||
waiters_per_dp = waiters.setdefault(dp.id, {})
|
||||
|
||||
@ -189,6 +189,44 @@ class Test_ofctl(unittest.TestCase):
|
||||
dp = ofproto_protocol.ProtocolDesc(version=test.ver)
|
||||
ofproto = dp.ofproto
|
||||
|
||||
vid_present = dp.ofproto.OFPVID_PRESENT
|
||||
expected_value = {
|
||||
"vlan_vid": {
|
||||
0: {"to_match": 0 | vid_present, "to_str": "0"},
|
||||
3: {"to_match": 3 | vid_present, "to_str": "3"},
|
||||
4095: {"to_match": 4095 | vid_present, "to_str": "4095"},
|
||||
"0": {"to_match": 0 | vid_present, "to_str": "0"},
|
||||
"3": {"to_match": 3 | vid_present, "to_str": "3"},
|
||||
"4095": {"to_match": 4095 | vid_present, "to_str": "4095"},
|
||||
"0x0000": {"to_match": 0x0000, "to_str": "0x0000"},
|
||||
"0x0003": {"to_match": 0x0003, "to_str": "0x0003"},
|
||||
"0x0fff": {"to_match": 0x0fff, "to_str": "0x0fff"},
|
||||
"0x1000": {"to_match": 0x1000, "to_str": "0"},
|
||||
"0x1003": {"to_match": 0x1003, "to_str": "3"},
|
||||
"0x1fff": {"to_match": 0x1fff, "to_str": "4095"},
|
||||
"4096/4096": {"to_match": (4096, 4096),
|
||||
"to_str": "0x1000/0x1000"},
|
||||
"4096/4097": {"to_match": (4096, 4097),
|
||||
"to_str": "0x1000/0x1001"},
|
||||
"2744/2748": {"to_match": (2744, 2748),
|
||||
"to_str": "0x0ab8/0x0abc"},
|
||||
"2748/2748": {"to_match": (2748, 2748),
|
||||
"to_str": "0x0abc/0x0abc"},
|
||||
"2748/2749": {"to_match": (2748, 2749),
|
||||
"to_str": "0x0abc/0x0abd"},
|
||||
"0x1000/0x1000": {"to_match": (0x1000, 0x1000),
|
||||
"to_str": "0x1000/0x1000"},
|
||||
"0x1000/0x1001": {"to_match": (0x1000, 0x1001),
|
||||
"to_str": "0x1000/0x1001"},
|
||||
"0x0ab8/0x0abc": {"to_match": (0x0ab8, 0x0abc),
|
||||
"to_str": "0x0ab8/0x0abc"},
|
||||
"0x0abc/0x0abc": {"to_match": (0x0abc, 0x0abc),
|
||||
"to_str": "0x0abc/0x0abc"},
|
||||
"0x0abc/0x0abd": {"to_match": (0x0abc, 0x0abd),
|
||||
"to_str": "0x0abc/0x0abd"}
|
||||
}
|
||||
}
|
||||
|
||||
# str -> match
|
||||
match = to_match(dp, attrs)
|
||||
|
||||
@ -230,8 +268,7 @@ class Test_ofctl(unittest.TestCase):
|
||||
eq_(ipv6, field_value)
|
||||
return
|
||||
elif key == 'vlan_vid':
|
||||
vid = value | ofproto.OFPVID_PRESENT
|
||||
eq_(vid, field_value)
|
||||
eq_(expected_value['vlan_vid'][value]['to_match'], field_value)
|
||||
return
|
||||
elif key == 'metadata':
|
||||
# Metadata
|
||||
@ -308,6 +345,9 @@ class Test_ofctl(unittest.TestCase):
|
||||
# without mask
|
||||
eq_(ipv6, field_value)
|
||||
return
|
||||
elif key == 'dl_vlan':
|
||||
eq_(expected_value['vlan_vid'][value]['to_str'], field_value)
|
||||
return
|
||||
elif key == 'metadata':
|
||||
# Metadata
|
||||
meta, mask = _to_match_metadata(value)
|
||||
@ -373,7 +413,28 @@ class test_data_v1_2():
|
||||
{'eth_dst': "aa:bb:cc:11:22:33"},
|
||||
{'eth_dst': "aa:bb:cc:11:22:33/00:00:00:00:ff:ff"},
|
||||
{'eth_type': 0x800},
|
||||
{'dl_vlan': 5},
|
||||
{'dl_vlan': 0},
|
||||
{'dl_vlan': 3},
|
||||
{'dl_vlan': 4095},
|
||||
{'dl_vlan': "0"},
|
||||
{'dl_vlan': "3"},
|
||||
{'dl_vlan': "4095"},
|
||||
{'dl_vlan': "0x0000"},
|
||||
{'dl_vlan': "0x0003"},
|
||||
{'dl_vlan': "0x0fff"},
|
||||
{'dl_vlan': "0x1000"},
|
||||
{'dl_vlan': "0x1003"},
|
||||
{'dl_vlan': "0x1fff"},
|
||||
{'dl_vlan': "4096/4096"},
|
||||
{'dl_vlan': "4096/4097"},
|
||||
{'dl_vlan': "2744/2748"},
|
||||
{'dl_vlan': "2748/2748"},
|
||||
{'dl_vlan': "2748/2749"},
|
||||
{'dl_vlan': "0x1000/0x1000"},
|
||||
{'dl_vlan': "0x1000/0x1001"},
|
||||
{'dl_vlan': "0x0ab8/0x0abc"},
|
||||
{'dl_vlan': "0x0abc/0x0abc"},
|
||||
{'dl_vlan': "0x0abc/0x0abd"},
|
||||
{'vlan_pcp': 3, 'vlan_vid': 3},
|
||||
{'ip_dscp': 3, 'eth_type': 0x0800},
|
||||
{'ip_ecn': 4, 'eth_type': 0x86dd},
|
||||
@ -395,7 +456,28 @@ class test_data_v1_2():
|
||||
{'tp_dst': 2, 'ip_proto': 6},
|
||||
{'tp_src': 3, 'ip_proto': 17},
|
||||
{'tp_dst': 4, 'ip_proto': 17},
|
||||
{'vlan_vid': 0},
|
||||
{'vlan_vid': 3},
|
||||
{'vlan_vid': 4095},
|
||||
{'vlan_vid': "0"},
|
||||
{'vlan_vid': "3"},
|
||||
{'vlan_vid': "4095"},
|
||||
{'vlan_vid': "0x0000"},
|
||||
{'vlan_vid': "0x0003"},
|
||||
{'vlan_vid': "0x0fff"},
|
||||
{'vlan_vid': "0x1000"},
|
||||
{'vlan_vid': "0x1003"},
|
||||
{'vlan_vid': "0x1fff"},
|
||||
{'vlan_vid': "4096/4096"},
|
||||
{'vlan_vid': "4096/4097"},
|
||||
{'vlan_vid': "2744/2748"},
|
||||
{'vlan_vid': "2748/2748"},
|
||||
{'vlan_vid': "2748/2749"},
|
||||
{'vlan_vid': "0x1000/0x1000"},
|
||||
{'vlan_vid': "0x1000/0x1001"},
|
||||
{'vlan_vid': "0x0ab8/0x0abc"},
|
||||
{'vlan_vid': "0x0abc/0x0abc"},
|
||||
{'vlan_vid': "0x0abc/0x0abd"},
|
||||
{'tcp_src': 3, 'ip_proto': 6},
|
||||
{'tcp_dst': 5, 'ip_proto': 6},
|
||||
{'udp_src': 2, 'ip_proto': 17},
|
||||
@ -590,7 +672,8 @@ def _add_tests_match(cls):
|
||||
for attr in cls.attr_list:
|
||||
for key, value in attr.items():
|
||||
method_name = 'test_' + \
|
||||
str(cls.ver) + '_' + key + '_' + str(value) + '_match'
|
||||
str(cls.ver) + '_' + key + '_' + str(
|
||||
value) + str(type(value)) + '_match'
|
||||
|
||||
def _run(self, name, attr, cls):
|
||||
print ('processing %s ...' % name)
|
||||
@ -604,6 +687,7 @@ def _add_tests_match(cls):
|
||||
im = new.instancemethod(func, None, Test_ofctl)
|
||||
setattr(Test_ofctl, method_name, im)
|
||||
|
||||
|
||||
""" Test case """
|
||||
|
||||
# for of12
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user