'id-pools', 'id-pool'],
'ifconfig': ['iface-config.log', 'config', 'ietf-interfaces:interfaces',
'interfaces', 'interface'],
+ 'itmconfig': ['itm-config.log', 'config' 'itm-state:dpn-teps-state',
+ 'dpn-teps-state', 'dpns-teps'],
'ifindexes': ['ifindexes.log', 'operational',
'odl-interface-meta:if-indexes-interface-map',
'if-indexes-interface-map', 'if-index-interface'],
'neutronvpn:neutron-vpn-portip-port-data',
'neutron-vpn-portip-port-data',
'vpn-portip-to-port'],
- 'tunconfig': ['tunnel-config.log', 'config', 'itm-state:tunnel-list',
- 'tunnel-list', 'internal-tunnel'],
+ 'neutrontrunks': ['neutron-trunks.log', 'config', 'neutron:neutron/trunks',
+ 'trunks', 'trunk'],
'tunconfig-external': ['tunnel-config-external.log', 'config',
'itm-state:external-tunnel-list',
'external-tunnel-list', 'external-tunnel'],
+ 'tunconfig': ['tunnel-config.log', 'config', 'itm-state:tunnel-list',
+ 'tunnel-list', 'internal-tunnel'],
'tunstate': ['tunnel-state.log', 'operational', 'itm-state:tunnels_state',
'tunnels_state', 'state-tunnel-list'],
'vpninstance-to-vpnid': ['vpninstance-to-vpnid.log', 'config',
-import collections
import constants as const
import ds_get_data as dsg
import flow_parser as fp
import json
import netvirt_utils as utils
-import ovs_get_data as og
+from collections import defaultdict
# Required
port = None
tunnel = None
tunState = None
- if iface.get('type') == const.IFTYPE_VLAN:
+ if iface and iface.get('type') == const.IFTYPE_VLAN:
ports = dsg.get_neutron_ports()
port = ports.get(ifname)
- elif iface.get('type') == const.IFTYPE_TUNNEL:
+ elif iface and iface.get('type') == const.IFTYPE_TUNNEL:
tunnels = dsg.get_config_tunnels()
tunnel = tunnels.get(ifname)
tunStates = dsg.get_tunnel_states()
def analyze_interface(ifname=None):
- global ifaces,ifstates
- ifaces = dsg.get_config_interfaces()
- ifstates = dsg.get_interface_states()
+ global ifaces, ifstates
if not ifname:
print_keys()
exit(1)
ifname = ifname[0]
+ ifaces = dsg.get_config_interfaces()
+ ifstates = dsg.get_interface_states()
iface,ifstate,port,tunnel,tunState = by_ifname(ifname)
print "InterfaceConfig: "
utils.pretty_print(iface)
def get_groups(ofnodes=None):
of_nodes = ofnodes or dsg.get_inventory_config()
key ='group-id'
- group_dict = collections.defaultdict(dict)
+ group_dict = defaultdict(dict)
for node in of_nodes.itervalues():
dpnid = utils.get_dpn_from_ofnodeid(node['id'])
for group in node[const.NODE_GROUP]:
#print 'Flow:', json.dumps(parse_flow(flow['flow']))
-def get_all_flows(modules=['ifm']):
+def get_all_flows(modules=['ifm'], filter=[]):
if not modules:
return 'No modules specified'
ifaces = {}
ifaces, ifstates, ifindexes,
fibentries, vpnids, vpninterfaces,
einsts, eifaces)
- if flow_dict is not None:
+ if (flow_dict is not None and
+ utils.filter_flow(flow_dict, filter)):
flows.append(flow_dict)
return flows
-def show_all_flows():
+def show_flows(modules=['ifm'], sort_by='table', filter_by=[]):
compute_map = get_dpn_host_mapping()
nports = dsg.get_neutron_ports()
- for flow in utils.sort(get_all_flows(['all']), 'table'):
+ for flow in utils.sort(get_all_flows(modules, filter_by), sort_by):
host = compute_map.get(flow.get('dpnid'), flow.get('dpnid'))
ip_list = get_ips_for_iface(nports, flow.get('ifname'))
if ip_list:
flow['table'], host, flow['id'],
utils.show_optionals(flow))
print result
- #print 'Flow:', json.dumps(parse_flow(flow['flow']))
+ print 'Flow:', json.dumps(parse_flow(flow['flow']))
+
+
+def show_all_flows():
+ show_flows(modules=['all'])
def show_elan_flows():
- for flow in utils.sort(get_stale_flows(['elan']), 'table'):
- print 'Table:', flow['table'], 'FlowId:', flow['id'], utils.show_optionals(flow)
- print 'Flow:', json.dumps(parse_flow(flow['flow']))
+ compute_map = get_dpn_host_mapping()
+ for flow in utils.sort(get_all_flows(['elan']), 'id'):
+ host = compute_map.get(flow.get('dpnid'), flow.get('dpnid'))
+ result = 'MacHost:{}{},Table:{},FlowId:{},{},Flow:{}'.format(flow['id'][-17:],host,flow['table'],flow['id'],utils.show_optionals(flow),json.dumps(parse_flow(flow['flow'])))
+ print result
+ #print 'Flow:', json.dumps(parse_flow(flow['flow']))
+
+
+def get_matchstr(flow):
+ if flow and flow.get('flow') and flow.get('flow').get('match'):
+ return json.dumps(flow.get('flow').get('match', None))
+
+
+def get_key_for_dup_detect(flow):
+ result = '{}:{}:{}'.format(flow.get('dpnid'), flow.get('table'), get_matchstr(flow))
+ return result
+
+
+def show_dup_flows():
+ mmac = dsg.get_mip_mac()
+ einsts = dsg.get_elan_instances()
+ flows = utils.sort(get_all_flows(['elan']), 'table')
+ matches = defaultdict(list)
+ compute_map = get_dpn_host_mapping()
+ for flow in flows:
+ dup_key = get_key_for_dup_detect(flow)
+ if dup_key:
+ if matches and matches.get(dup_key):
+ matches[dup_key].append(flow)
+ else:
+ matches[dup_key].append(flow)
+ for k, v in matches.iteritems():
+ if len(v) > 1:
+ dpnid = k.split(':')[0]
+ host = compute_map.get(dpnid, dpnid)
+ result = 'Host:{},FlowCount:{},MatchKey:{},ElanTag:{}'.format(host, len(v), k,v[0].get('elan-tag'))
+ print result
+ for idx, flow in enumerate(v):
+ result = "Duplicate"
+ mac_addr = flow.get('dst-mac')
+ if mac_addr and mmac.get(mac_addr):
+ result = fp.is_correct_elan_flow(flow, mmac.get(mac_addr), einsts, host)
+ print ' {}Flow-{}:{}'.format(result, idx, json.dumps(parse_flow(flow.get('flow'))))
+
+
+def show_learned_mac_flows():
+ nports = dsg.get_neutron_ports(key_field='mac-address')
+ flows = utils.sort(get_all_flows(['elan']), 'table')
+ compute_map = get_dpn_host_mapping()
+ for flow_info in flows:
+ flow = flow_info.get('flow')
+ dpnid = flow_info.get('dpnid')
+ host = compute_map.get(dpnid, dpnid)
+ if ((flow_info.get('table') == 50 and
+ flow.get('idle-timeout') == 300 and not
+ nports.get(flow_info.get('src-mac'))) or
+ (flow_info.get('table') == 51 and
+ not nports.get(flow_info.get('dst-mac')))):
+ result = 'Table:{},Host:{},FlowId:{}{}'.format(
+ flow_info.get('table'), host, flow.get('id'),
+ utils.show_optionals(flow_info))
+ print result
+ print 'Flow:{}'.format(json.dumps(parse_flow(flow)))
def show_elan_instances():
def show_idpools():
+ ports = dsg.get_neutron_ports()
+ iface_ids = []
for k,v in get_duplicate_ids().iteritems():
result = "Id:{},Keys:{}".format(k, json.dumps(v.get('id-keys')))
if v.get('pool-name'):
result = "{},Pool:{}".format(result, v.get('pool-name'))
+ if v.get('pool-name') == 'interfaces':
+ iface_ids.extend(v.get('id-keys'))
if v.get('parent-pool-name'):
result = "{},ParentPool:{}".format(result, v.get('parent-pool-name'))
print result
+ print "\nNeutron Ports"
+ print "============="
+ for id in iface_ids:
+ port = ports.get(id, {})
+ print "Iface={}, NeutronPort={}".format(id, json.dumps(port))
def parse_flow(flow):
print 'Dpn:', dpn, 'ID:', group_key, 'Group:', json.dumps(groups[dpn][group_key])
+def analyze_trunks():
+ nports = dsg.get_neutron_ports()
+ ntrunks = dsg.get_neutron_trunks()
+ vpninterfaces = dsg.get_vpninterfaces()
+ ifaces = dsg.get_config_interfaces()
+ ifstates = dsg.get_interface_states()
+ subport_dict = {}
+ for v in ntrunks.itervalues():
+ nport = nports.get(v.get('port-id'))
+ s_subports = []
+ for subport in v.get('sub-ports'):
+ sport_id = subport.get('port-id')
+ snport = nports.get(sport_id)
+ svpniface = vpninterfaces.get(sport_id)
+ siface = ifaces.get(sport_id)
+ sifstate = ifstates.get(sport_id)
+ subport['SubNeutronPort'] = 'Correct' if snport else 'Wrong'
+ subport['SubVpnInterface'] = 'Correct' if svpniface else 'Wrong'
+ subport['ofport'] = utils.get_ofport_from_ncid(sifstate.get('lower-layer-if')[0])
+ if siface:
+ vlan_mode = siface.get('odl-interface:l2vlan-mode')
+ parent_iface_id = siface.get('odl-interface:parent-interface')
+ if vlan_mode !='trunk-member':
+ subport['SubIface'] = 'WrongMode'
+ elif parent_iface_id !=v.get('port-id'):
+ subport['SubIface'] = 'WrongParent'
+ elif siface.get('odl-interface:vlan-id') !=subport.get('segmentation-id'):
+ subport['SubIface'] = 'WrongVlanId'
+ else:
+ subport['SubIface'] = 'Correct'
+ else:
+ subport['SubIface'] = 'Wrong'
+ s_subport = 'SegId:{},PortId:{},SubNeutronPort:{},SubIface:{},SubVpnIface:{}'.format(
+ subport.get('segmentation-id'),subport.get('port-id'),
+ subport.get('SubNeutronPort'),
+ subport.get('SubIface'),
+ subport.get('SubVpnInterface'))
+ s_subports.append(subport)
+ subport_dict[subport['port-id']] = subport
+ s_trunk = 'TrunkName:{},TrunkId:{},PortId:{},NeutronPort:{},SubPorts:{}'.format(
+ v.get('name'), v.get('uuid'), v.get('port-id'),
+ 'Correct' if nport else 'Wrong', json.dumps(s_subports))
+ print s_trunk
+ print '\n------------------------------------'
+ print 'Analyzing Flow status for SubPorts'
+ print '------------------------------------'
+ for flow in utils.sort(get_all_flows(['ifm'], ['vlanid']), 'ifname'):
+ subport = subport_dict.get(flow.get('ifname')) or None
+ vlanid = subport.get('segmentation-id') if subport else None
+ ofport = subport.get('ofport') if subport else None
+ flow_status = 'Okay'
+ if flow.get('ofport') and flow.get('ofport') != ofport:
+ flow_status = 'OfPort mismatch for SubPort:{} and Flow:{}'.format(subport, flow.get('flow'))
+ if flow.get('vlanid') and flow.get('vlanid') != vlanid:
+ flow_status = 'VlanId mismatch for SubPort:{} and Flow:{}'.format(subport, flow.get('flow'))
+ if subport:
+ print 'SubPort:{},Table:{},FlowStatus:{}'.format(
+ subport.get('port-id'), flow.get('table'), flow_status)
+
+
def main(args=None):
options, args = utils.parse_args()
if options.callMethod:
#analyze_inventory('openflow:165862438671169',ifName='tunf94333cc491')
#show_stale_flows()
#show_stale_bindings()
- analyze_interface(args)
+ analyze_interface([args[1]])
#og.print_flow_dict(og.get_ofctl_flows())
return if_dict
-def get_neutron_ports(file_name=None):
+def get_itm_config_interfaces(file_name=None):
+ tun_dict = {}
+ tunifaces = get_ds_data('itmconfig',file_name)
+ for sourcedpn in tunifaces:
+ for remotedpn in sourcedpn['remote-dpns']:
+ tun_dict[remotedpn['tunnel-name']] = remotedpn
+ return tun_dict
+
+
+def get_neutron_ports(file_name=None, key_field='uuid'):
port_dict = {}
ports = get_ds_data('neutronports',file_name)
for port in ports:
- port_dict[port['uuid']] = port
+ port_dict[port[key_field]] = port
return port_dict
+def get_neutron_trunks(file_name=None):
+ trunk_dict = {}
+ trunks = get_ds_data('neutrontrunks',file_name)
+ for trunk in trunks:
+ trunk_dict[trunk['uuid']] = trunk
+ return trunk_dict
+
+
def get_interface_states(file_name=None):
ifs_dict = {}
ifstates = get_ds_data('ifstate',file_name)
return nodes_dict
+
def get_inventory_config(file_name=None):
return get_inventory_nodes(file_name)
for idpool in idpools:
idpools_dict[idpool['pool-name']] = idpool
return idpools_dict
+
+
+def get_mip_mac(filename='mip-mac.log'):
+ mmac_dict = collections.defaultdict(dict)
+ try:
+ with open(filename) as data_file:
+ data = json.load(data_file)
+ except IOError:
+ data = []
+ for entry in data:
+ entry['mac'] = entry['mac'].lower()
+ mmac_dict[entry.get('mac')][entry.get('network-id')] = entry
+ return mmac_dict
import constants as const
-OPTIONALS = ['ifname', 'lport', 'elan-tag', 'mpls', 'vpnid', 'reason']
+OPTIONALS = ['ifname', 'lport', 'elan-tag', 'mpls', 'vpnid', 'reason',
+ 'dst-mac', 'src-mac', 'ofport', 'vlanid']
MAC_LEN = 17
# Flow table constants
def stale_ifm_flow(flow, flow_info, ifaces, ifstates):
get_flow_info_from_ifm_table(flow_info, flow)
flow_ifname = flow_info['ifname']
- if flow_ifname is not None and not ifaces.get(flow_ifname):
+ iface = ifaces.get(flow_ifname)
+ if flow_ifname is not None and not iface:
flow_info['reason'] = 'Interface doesnt exist'
return create_flow_dict(flow_info, flow)
elif flow_ifname and ifstates.get(flow_ifname):
and flow_info['lport'] != ifstate['if-index']):
flow_info['reason'] = 'Lport and IfIndex mismatch'
return create_flow_dict(flow_info, flow)
+ if (flow_info.get('ofport') and ifstate.get('lower-layer-if')
+ and flow_info['ofport'] != utils.get_ofport_from_ncid(
+ ifstate.get('lower-layer-if')[0])):
+ flow_info['reason'] = 'OfPort mismatch'
+ if (flow_info.get('vlanid') and iface.get('odl-interface:vlan-id')
+ and flow_info['vlanid'] != iface.get('odl-interface:vlan-id')):
+ flow_info['reason'] = 'VlanId mismatch'
return None
# return create_flow_dict(flow_info, flow)
iface = get_iface_for_lport(ifaces, ifindexes, lport)
if lport and not iface:
flow_info['reason'] = 'Interface for lport not found'
- #return create_flow_dict(flow_info, flow)
+ return create_flow_dict(flow_info, flow)
if iface:
flow_info['ifname'] = iface['name']
if not is_elantag_valid(eltag, eifaces, einsts, iface):
flow_info['reason'] = 'Lport Elantag mismatch'
- #return create_flow_dict(flow_info, flow)
- return create_flow_dict(flow_info, flow)
- #return None
+ return create_flow_dict(flow_info, flow)
+ #return create_flow_dict(flow_info, flow)
+ return None
def is_elantag_valid(eltag, eifaces, einsts, iface):
return True
+def is_correct_elan_flow(flow_info, mmac, einsts, flow_host):
+ flow = flow_info.get('flow')
+ flow_etag = flow_info.get('elan-tag')
+ for k, v in mmac.iteritems():
+ mac_host = v.get('compute')
+ if einsts.get(k):
+ einst_tag = einsts.get(k).get('elan-tag')
+ #print einst_tag, flow_etag, mac_host
+ if flow_etag and einst_tag and flow_etag == einst_tag:
+ if mac_host.startswith(flow_host):
+ act_resubmit = get_act_resubmit(flow)
+ if (act_resubmit and act_resubmit.get('table') == 220):
+ return 'Correct'
+ else:
+ act_tunnel = get_act_set_tunnel(flow)
+ if act_tunnel:
+ return 'Correct'
+ return 'Wrong'
+ return 'Wrong'
+
+
def get_iface_for_lport(ifaces, ifindexes, lport):
if lport:
if ifindexes.get(lport):
return action['group-action']
+def get_act_set_tunnel(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 'tunnel' in action.get('set-field'):
+ return action.get('set-field').get('tunnel')
+
+
+def get_act_resubmit(flow):
+ for instruction in flow['instructions'].get('instruction', []):
+ if 'apply-actions' in instruction:
+ for action in instruction['apply-actions'].get('action', []):
+ if ('openflowplugin-extension-nicira-action:nx-resubmit'
+ in action):
+ return action[
+ 'openflowplugin-extension-nicira-action:nx-resubmit']
+
+
+def get_act_set_vlanid(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 'vlan-match' in action.get('set-field'):
+ return action.get('set-field').get('vlan-match').get('vlan-id')
+
+
+def get_act_output(flow):
+ for instruction in flow['instructions'].get('instruction', []):
+ if 'apply-actions' in instruction:
+ for action in instruction['apply-actions'].get('action', []):
+ if 'output-action' in action and 'output-node-connector' in action.get('output-action'):
+ return action.get('output-action')
+
+
def get_match_metadata(flow):
return flow['match'].get('metadata')
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
+
+
+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
+
+
+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_flow_info_from_any(flow_info, flow):
w_mdata = get_instruction_writemeta(flow)
if w_mdata:
lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
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()
return flow_info
# Table specific parsing
if (mask & LPORT_MASK):
lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
flow_info['lport'] = int(lport, 16)
- return flow_info
m_reg6 = get_match_reg6(flow)
- if m_reg6 and m_reg6.get('value'):
+ 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 flow['table_id'] == 0:
+ m_inport = get_match_inport(flow)
+ if m_inport:
+ flow_info['ofport'] = utils.get_ofport_from_ncid(m_inport)
+ m_vlan = get_match_vlanid(flow)
+ if m_vlan and m_vlan.get('vlan-id'):
+ flow_info['vlanid'] = m_vlan.get('vlan-id')
+ elif flow['table_id'] == 220:
+ a_output = get_act_output(flow)
+ a_vlan = get_act_set_vlanid(flow)
+ if a_output and a_output.get('output-node-connector'):
+ flow_info['ofport'] = a_output.get('output-node-connector')
+ if a_vlan and a_vlan.get('vlan-id'):
+ flow_info['vlanid'] = a_vlan.get('vlan-id')
return flow_info
if (mask & LPORT_MASK):
lport = ('%x' % (metadata & LPORT_MASK))[:-LPORT_MASK_ZLEN]
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 flow_info.get('lport'):
reg6_load = get_act_reg6load(flow)
if reg6_load and reg6_load.get('value'):
def get_dpn_from_ofnodeid(node_id):
- return node_id.split(':')[1]
+ return node_id.split(':')[1] if node_id else 'none'
+
+
+def get_ofport_from_ncid(ncid):
+ return ncid.split(':')[2] if ncid and ncid.startswith('openflow') else 0
def to_hex(data, ele=None):
return sorted(data, key=lambda x: x[field])
+def filter_flow(flow_dict, filter_list):
+ if not filter_list:
+ return True
+ for flow_filter in filter_list:
+ if flow_dict.get(flow_filter):
+ return True
+ return False
+
+
def show_optionals(flow):
result = ''
lport = flow.get('lport')
label = flow.get('mpls')
vpnid = flow.get('vpnid')
ip = flow.get('iface-ips')
+ smac = flow.get('src-mac')
+ dmac = flow.get('dst-mac')
+ vlanid = flow.get('vlanid')
+ ofport = flow.get('ofport')
if lport:
result = '{},LportTag:{}/{}'.format(result, lport, to_hex(lport))
+ if ofport:
+ result = '{},OfPort:{}'.format(result, ofport)
+ if vlanid:
+ result = '{},VlanId:{}'.format(result, vlanid)
if vpnid:
result = '{},VpnId:{}/{}'.format(result, vpnid, to_hex(vpnid*2))
if label:
result = '{},MplsLabel:{}'.format(result, label)
if elantag:
result = '{},ElanTag:{}/{}'.format(result, elantag, to_hex(elantag))
+ if smac:
+ result = '{},SrcMac:{}'.format(result, smac)
+ if dmac:
+ result = '{},DstMac:{}'.format(result, dmac)
if ip:
result = '{},LportIp:{}'.format(result, json.dumps(ip))
result = '{},Reason:{}'.format(result, flow.get('reason'))