+# Copyright 2018 Red Hat, Inc. and others. All Rights Reserved.
+#
+# 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.
+
from odltools.mdsal.models.model import Model
-import utils
+from odltools.netvirt import utils
MAC_LEN = 17
LPORT_REG6_MASK = 0xfffff00
LPORT_REG6_MASK_ZLEN = 2
VRFID_MASK = 0x0000000000fffffe
+SERVICE_ID_MASK = 0xf000000000000000
+SERVICE_ID_MASK_ZLEN = 15
def parse_flow(flow):
for instruction in flow['instructions'].get('instruction', []):
if 'write-metadata' in instruction:
return instruction['write-metadata']
- return None
def get_act_reg6load(flow):
for action in instruction['apply-actions'].get('action', []):
if 'openflowplugin-extension-nicira-action:nx-reg-load' in action:
return action['openflowplugin-extension-nicira-action:nx-reg-load']
- return None
def get_act_conntrack(flow):
return action.get('output-action')
+def get_act_set_ipv4_dest(flow):
+ for instruction in flow['instructions'].get('instruction', []):
+ if 'apply-actions' in instruction:
+ for action in instruction['apply-actions'].get('action', []):
+ if 'set-field' in action and 'ipv4-destination' in action.get('set-field'):
+ return action.get('set-field').get('ipv4-destination')
+
+
+def get_act_set_ipv4_src(flow):
+ for instruction in flow['instructions'].get('instruction', []):
+ if 'apply-actions' in instruction:
+ for action in instruction['apply-actions'].get('action', []):
+ if 'set-field' in action and 'ipv4-source' in action.get('set-field'):
+ return action.get('set-field').get('ipv4-source')
+
+
def get_match_metadata(flow):
return flow['match'].get('metadata')
return (
ofex['extension']
['openflowplugin-extension-nicira-match:nxm-nx-reg'])
- return None
def get_match_mpls(flow):
if flow['match'].get('protocol-match-fields'):
return flow['match'].get('protocol-match-fields').get('mpls-label')
- return None
def get_match_tunnelid(flow):
if flow['match'].get('tunnel'):
return flow['match'].get('tunnel').get('tunnel-id')
- return None
def get_match_ether_dest(flow):
if flow.get('match').get('ethernet-match') and flow['match'].get('ethernet-match').get('ethernet-destination'):
- return flow['match'].get('ethernet-match').get('ethernet-destination')
- return None
+ return flow['match'].get('ethernet-match').get('ethernet-destination').get('address')
def get_match_ether_src(flow):
if flow.get('match').get('ethernet-match') and flow['match'].get('ethernet-match').get('ethernet-source'):
- return flow['match'].get('ethernet-match').get('ethernet-source')
- return None
+ return flow['match'].get('ethernet-match').get('ethernet-source').get('address')
+
+
+def get_match_ipv4_dest(flow):
+ return utils.parse_ipv4(flow['match'].get('ipv4-destination'))
+
+
+def get_match_ipv4_src(flow):
+ return utils.parse_ipv4(flow['match'].get('ipv4-source'))
def get_match_vlanid(flow):
if flow.get('match').get('vlan-match') and flow['match'].get('vlan-match').get('vlan-id'):
return flow['match'].get('vlan-match').get('vlan-id')
- return None
def get_match_inport(flow):
if flow.get('match').get('in-port'):
return flow['match'].get('in-port')
- return None
+
+
+def get_lport_from_mreg6(m_reg6):
+ if m_reg6 and m_reg6.get('value'):
+ return (('%x' % (m_reg6.get('value') & LPORT_REG6_MASK))[:-LPORT_REG6_MASK_ZLEN])
+
+
+def get_lport_from_metadata(metadata, mask):
+ if mask & LPORT_MASK:
+ return ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
+
+
+def get_elan_from_metadata(metadata, mask):
+ if mask & ELAN_TAG_MASK:
+ return ('%x' % (metadata & ELAN_TAG_MASK))[:ELAN_HEX_LEN]
+
+
+def get_service_id_from_metadata(metadata, mask):
+ if mask & SERVICE_ID_MASK:
+ return ('%x' % (metadata & SERVICE_ID_MASK))[:-SERVICE_ID_MASK_ZLEN]
+
+
+def get_vpnid_from_metadata(metadata, mask):
+ if mask & VRFID_MASK:
+ return (metadata & VRFID_MASK) / 2
def get_flow_info_from_any(flow_info, flow):
w_mdata = get_instruction_writemeta(flow)
- lport = None
+ lport = flow_info.get('lport') if flow_info else None
+ serviceid = flow_info.get('serviceid') if flow_info else None
if w_mdata:
metadata = w_mdata['metadata']
mask = w_mdata['metadata-mask']
- if mask & LPORT_MASK:
- lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
- if lport:
- flow_info['lport'] = int(lport, 16)
+ lport = get_lport_from_metadata(metadata, mask) if not lport else lport
+ if lport:
+ flow_info['lport'] = int(lport, 16)
+ serviceid = get_service_id_from_metadata(metadata, mask) if not serviceid else serviceid
+ if serviceid:
+ flow_info['serviceid'] = int(serviceid, 16)
m_metadata = get_match_metadata(flow)
if m_metadata:
+ elan = flow_info.get('elan-tag')
+ vpnid = flow_info.get('vpnid')
metadata = m_metadata['metadata']
mask = m_metadata['metadata-mask']
- if mask & ELAN_TAG_MASK:
- elan = ('%x' % (metadata & ELAN_TAG_MASK))[:ELAN_HEX_LEN]
- if elan:
- flow_info['elan-tag'] = int(elan, 16)
- if not lport and (mask & LPORT_MASK):
- lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
+ if not lport:
+ lport = get_lport_from_metadata(metadata, mask)
if lport:
flow_info['lport'] = int(lport, 16)
- m_ether_dest = get_match_ether_dest(flow)
- if m_ether_dest and m_ether_dest.get('address'):
- flow_info['dst-mac'] = m_ether_dest.get('address').lower()
- m_ether_src = get_match_ether_src(flow)
- if m_ether_src and m_ether_src.get('address'):
- flow_info['src-mac'] = m_ether_src.get('address').lower()
+ if not serviceid:
+ serviceid = get_service_id_from_metadata(metadata, mask)
+ flow_info['serviceid'] = int(serviceid, 16)
+ if not elan:
+ elan = get_elan_from_metadata(metadata, mask)
+ if elan:
+ flow_info['elan-tag'] = int(elan, 16)
+ if not vpnid:
+ vpnid = get_vpnid_from_metadata(metadata, mask)
+ if vpnid:
+ flow_info['vpnid'] = vpnid
+ if not flow_info.get('dst-mac'):
+ m_ether_dest = get_match_ether_dest(flow)
+ if m_ether_dest:
+ flow_info['dst-mac'] = m_ether_dest.lower()
+ if not flow_info.get('src-mac'):
+ m_ether_src = get_match_ether_src(flow)
+ if m_ether_src:
+ flow_info['src-mac'] = m_ether_src.lower()
+ if not flow_info.get('dst-ip4'):
+ m_ipv4_dest = get_match_ipv4_dest(flow)
+ if m_ipv4_dest:
+ flow_info['dst-ip4'] = m_ipv4_dest
+ if not flow_info.get('src-ip4'):
+ m_ipv4_src = get_match_ipv4_src(flow)
+ if m_ipv4_src:
+ flow_info['src-ip4'] = m_ipv4_src
return flow_info
# Table specific parsing
if w_mdata:
metadata = w_mdata['metadata']
mask = w_mdata['metadata-mask']
- if mask & LPORT_MASK:
- lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
+ lport = get_lport_from_metadata(metadata, mask)
+ if lport:
flow_info['lport'] = int(lport, 16)
+ service_id = get_service_id_from_metadata(metadata, mask)
+ if service_id:
+ flow_info['serviceid'] = int(service_id, 16)
m_reg6 = get_match_reg6(flow)
- if not flow.get('lport') and m_reg6 and m_reg6.get('value'):
- lport = (('%x' % (m_reg6.get('value') & LPORT_REG6_MASK))
- [:-LPORT_REG6_MASK_ZLEN])
- flow_info['lport'] = int(lport, 16)
+ if not flow.get('lport'):
+ lport = get_lport_from_mreg6(m_reg6)
+ if lport:
+ flow_info['lport'] = int(lport, 16)
if flow['table_id'] == 0:
m_inport = get_match_inport(flow)
if m_inport:
if m_metadata:
metadata = m_metadata['metadata']
mask = m_metadata['metadata-mask']
- if mask & LPORT_MASK:
- lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
+ lport = get_lport_from_metadata(metadata, mask)
+ if lport:
flow_info['lport'] = int(lport, 16)
- if mask & VRFID_MASK:
+ vpnid = get_vpnid_from_metadata(metadata, mask)
+ if vpnid:
flow_info['vpnid'] = (metadata & VRFID_MASK) / 2
return flow_info
if m_metadata:
metadata = m_metadata['metadata']
mask = m_metadata['metadata-mask']
- if mask & ELAN_TAG_MASK:
- elan = ('%x' % (metadata & ELAN_TAG_MASK))[:ELAN_HEX_LEN]
+ elan = get_elan_from_metadata(metadata, mask)
+ if elan:
+ flow_info['lport'] = int(elan, 16)
flow_info['elan-tag'] = int(elan, 16)
- if mask & LPORT_MASK:
- lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
+ lport = get_lport_from_metadata(metadata, mask)
+ if lport:
flow_info['lport'] = int(lport, 16)
m_ether_dest = get_match_ether_dest(flow)
- if m_ether_dest and m_ether_dest.get('address'):
- flow_info['dst-mac'] = m_ether_dest.get('address').lower()
+ if m_ether_dest:
+ flow_info['dst-mac'] = m_ether_dest.lower()
m_ether_src = get_match_ether_src(flow)
- if m_ether_src and m_ether_src.get('address'):
- flow_info['src-mac'] = m_ether_src.get('address').lower()
+ if m_ether_src:
+ flow_info['src-mac'] = m_ether_src.lower()
if not flow_info.get('lport'):
reg6_load = get_act_reg6load(flow)
if reg6_load and reg6_load.get('value'):
if m_metadata:
metadata = m_metadata['metadata']
mask = m_metadata['metadata-mask']
- if mask & LPORT_MASK:
- lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
+ lport = get_lport_from_metadata(metadata, mask)
+ if lport:
flow_info['lport'] = int(lport, 16)
a_conntrk = get_act_conntrack(flow)
if a_conntrk and a_conntrk.get('conntrack-zone'):
return flow_info
+def get_flow_info_from_nat_table(flow_info, flow):
+ m_metadata = get_match_metadata(flow)
+ vpnid = None
+ if m_metadata:
+ metadata = m_metadata['metadata']
+ mask = m_metadata['metadata-mask']
+ lport = get_lport_from_metadata(metadata, mask)
+ if lport:
+ flow_info['lport'] = int(lport, 16)
+ vpnid = get_vpnid_from_metadata(metadata, mask)
+ if vpnid:
+ flow_info['vpnid'] = vpnid
+ if not vpnid:
+ w_metadata = get_instruction_writemeta(flow)
+ metadata = w_metadata['metadata']
+ mask = w_metadata['metadata-mask']
+ vpnid = get_vpnid_from_metadata(metadata, mask)
+ if vpnid:
+ flow_info['vpnid'] = vpnid
+ m_ipv4_dest = get_match_ipv4_dest(flow)
+ m_ipv4_src = get_match_ipv4_src(flow)
+ a_set_ipv4_dest = get_act_set_ipv4_dest(flow)
+ a_set_ipv4_src = get_act_set_ipv4_src(flow)
+ m_ether_src = get_match_ether_src(flow)
+ if flow['table_id'] in [25, 27]:
+ if a_set_ipv4_dest:
+ flow_info['int-ip4'] = a_set_ipv4_dest
+ if m_ipv4_dest:
+ flow_info['ext-ip4'] = m_ipv4_dest
+ m_ether_dest = get_match_ether_dest(flow)
+ if m_ether_dest:
+ flow_info['ext-mac'] = m_ether_dest
+ if flow['table_id'] in [26, 28]:
+ if a_set_ipv4_src:
+ flow_info['ext-ip4'] = a_set_ipv4_src
+ if m_ipv4_src:
+ flow_info['int-ip4'] = m_ipv4_src
+ m_ether_src = get_match_ether_src(flow)
+ if m_ether_src:
+ flow_info['ext-mac'] = m_ether_src
+ return flow_info
+
+
def get_flow_info_from_acl_table_flowid(flow_info, flow):
"""
Format for ACL flow ids is as follows: