1 import constants as const
2 import ds_get_data as dsg
3 import flow_parser as fp
5 import netvirt_utils as utils
6 from collections import defaultdict
20 def by_ifname(ifname):
21 ifstate = ifstates.get(ifname)
22 iface = ifaces.get(ifname)
26 if iface and iface.get('type') == const.IFTYPE_VLAN:
27 ports = dsg.get_neutron_ports()
28 port = ports.get(ifname)
29 elif iface and iface.get('type') == const.IFTYPE_TUNNEL:
30 tunnels = dsg.get_config_tunnels()
31 tunnel = tunnels.get(ifname)
32 tunStates = dsg.get_tunnel_states()
33 tunState = tunStates.get(ifname)
35 print "UNSUPPORTED IfType"
36 return iface,ifstate,port,tunnel,tunState
40 print "InterfaceNames: ", ifaces.keys()
42 print "IfStateNames: ", ifstates.keys()
45 def analyze_interface(ifname=None):
46 global ifaces, ifstates
51 ifaces = dsg.get_config_interfaces()
52 ifstates = dsg.get_interface_states()
53 iface,ifstate,port,tunnel,tunState = by_ifname(ifname)
54 print "InterfaceConfig: "
55 json.dumps(iface, indent=2)
56 print "InterfaceState: "
57 json.dumps(ifstate, indent=2)
60 json.dumps(port, indent=2)
61 analyze_neutron_port(port, iface, ifstate)
65 json.dumps(tunnel, indent=2)
68 json.dumps(tunState, indent=2)
70 ncId = ifstate.get('lower-layer-if')[0]
71 nodeId = ncId[:ncId.rindex(':')]
72 analyze_inventory(nodeId, True, ncId, ifname)
73 #analyze_inventory(nodeId, False, ncId, ifname)
75 def analyze_neutron_port(port, iface, ifstate):
76 for flow in utils.sort(get_all_flows(['all']), 'table'):
77 if ((flow.get('ifname') == port['uuid']) or
78 (flow.get('lport') and ifstate and flow['lport'] == ifstate.get('if-index')) or
79 (iface['name'] == flow.get('ifname'))):
80 result = 'Table:{},FlowId:{}{}'.format(
81 flow['table'], flow['id'],
82 utils.show_optionals(flow))
84 print 'Flow:', json.dumps(parse_flow(flow.get('flow')))
87 def analyze_inventory(nodeId, isConfig=True, ncId=None, ifName=None):
89 nodes = dsg.get_inventory_config()
90 print "Inventory Config:"
92 print "Inventory Operational:"
93 nodes = dsg.get_inventory_oper()
94 node = nodes.get(nodeId)
95 tables = node.get(const.NODE_TABLE)
96 groups = node.get(const.NODE_GROUP)
100 for flow in table.get('flow', []):
101 if not ifName or ifName in utils.nstr(flow.get('flow-name')):
103 flow_dict['table'] = table['id']
104 flow_dict['id'] = flow['id']
105 flow_dict['name'] = flow.get('flow-name')
106 flow_dict['flow'] = flow
107 flow_list.append(flow_dict)
108 flows = sorted(flow_list, key=lambda x: x['table'])
110 print 'Table:', flow['table']
111 print 'FlowId:', flow['id'], 'FlowName:', flow.get('name')
114 def get_dpn_host_mapping(oper_nodes=None):
116 nodes = oper_nodes or dsg.get_inventory_oper()
117 for node in nodes.itervalues():
118 dpnid = utils.get_dpn_from_ofnodeid(node['id'])
119 nodes_dict[dpnid] = node.get('flow-node-inventory:description', '')
123 def get_groups(ofnodes=None):
124 of_nodes = ofnodes or dsg.get_inventory_config()
126 group_dict = defaultdict(dict)
127 for node in of_nodes.itervalues():
128 dpnid = utils.get_dpn_from_ofnodeid(node['id'])
129 for group in node.get(const.NODE_GROUP, []):
130 if group_dict.get(dpnid) and group_dict.get(dpnid).get(group[key]):
131 print 'Duplicate:', dpnid, group[key]
132 group_dict[dpnid][group[key]] = group
133 return dict(group_dict)
136 def get_stale_flows(modules=['ifm']):
138 return 'No modules specified'
149 table_list = list(set([table for module in modules for table in const.TABLE_MAP[module]]))
150 ##table_list = [214, 244]
151 of_nodes = dsg.get_inventory_config()
153 ifaces = dsg.get_config_interfaces()
154 ifstates = dsg.get_interface_states()
155 if 'l3vpn' in modules:
156 ifaces = ifaces or dsg.get_config_interfaces()
157 ifindexes = ifindexes or dsg.get_ifindexes()
158 fibentries = fibentries or dsg.get_fibentries_by_label()
159 vpnids = vpnids or dsg.get_vpnids()
160 vpninterfaces = vpninterfaces or dsg.get_vpninterfaces()
161 groups = groups or get_groups(of_nodes)
163 ifaces = ifaces or dsg.get_config_interfaces()
164 ifindexes = ifindexes or dsg.get_ifindexes()
165 einsts = einsts or dsg.get_elan_instances()
166 eifaces = eifaces or dsg.get_elan_interfaces()
167 if 'elan' in modules:
168 ifaces = ifaces or dsg.get_config_interfaces()
169 einsts = einsts or dsg.get_elan_instances()
170 eifaces = eifaces or dsg.get_elan_interfaces()
171 ifindexes = ifindexes or dsg.get_ifindexes()
173 for node in of_nodes.itervalues():
174 tables = [x for x in node[const.NODE_TABLE] if x['id'] in table_list]
176 for flow in table.get('flow', []):
179 flow_info['dpnid'] = utils.get_dpn_from_ofnodeid(node['id'])
180 if 'ifm' in modules and table['id'] in const.TABLE_MAP['ifm']:
181 flow_dict = fp.stale_ifm_flow(flow, flow_info, ifaces, ifstates)
182 if 'l3vpn' in modules and table['id'] in const.TABLE_MAP['l3vpn']:
183 flow_dict = fp.stale_l3vpn_flow(flow, flow_info, groups, ifaces, ifindexes, vpnids, vpninterfaces, fibentries)
184 if 'elan' in modules and table['id'] in const.TABLE_MAP['elan']:
185 flow_dict = fp.stale_elan_flow(flow, flow_info, ifaces, ifindexes, einsts, eifaces)
186 if 'acl' in modules and table['id'] in const.TABLE_MAP['acl']:
187 flow_dict = fp.stale_acl_flow(flow, flow_info, ifaces, ifindexes, einsts, eifaces)
188 if flow_dict is not None:
189 stale_flows.append(flow_dict)
194 def show_stale_bindings():
195 stale_ids, bindings = get_stale_bindings()
196 for iface_id in sorted(stale_ids):
197 for binding in bindings[iface_id].itervalues():
198 #if binding.get('bound-services'):
199 path = get_data_path('bindings', binding)
200 print json.dumps(bindings[iface_id])
201 print('http://192.168.2.32:8383/restconf/config/{}'.format(path))
204 def get_stale_bindings():
205 ifaces = dsg.get_config_interfaces()
206 bindings, orphans = dsg.get_service_bindings()
207 return set(bindings.keys()) - set(ifaces.keys()), bindings
210 def get_ips_for_iface(nports, ifname):
212 port = nports.get(ifname) if ifname else None
213 fixed_ips = port.get('fixed-ips', []) if port else []
214 for fixed_ip in fixed_ips:
215 ips.append(fixed_ip['ip-address'])
219 def show_link_flow_binding():
220 stale_ids, bindings = get_stale_bindings()
221 flows = get_stale_flows()
222 print len(stale_ids), len(flows)
224 if flow['ifname'] in stale_ids and 'bound-services' in bindings[flow['ifname']]:
225 print 'Flow with binding: ', flow['ifname']
227 print 'Flow without binding: ', flow['ifname']
230 def show_stale_flows(sort_by='table'):
231 compute_map = get_dpn_host_mapping()
232 nports = dsg.get_neutron_ports()
233 for flow in utils.sort(get_stale_flows(['ifm', 'acl', 'elan', 'l3vpn']), sort_by):
234 host = compute_map.get(flow.get('dpnid'), flow.get('dpnid'))
235 ip_list = get_ips_for_iface(nports, flow.get('ifname'))
237 flow['iface-ips'] = ip_list
238 result = 'Table:{},Host:{},FlowId:{}{}'.format(
239 flow['table'], host, flow['id'],
240 utils.show_optionals(flow))
242 ##path = get_data_path('flows', flow)
243 #print('http://192.168.2.32:8383/restconf/config/{}'.format(path))
244 #print 'Flow:', json.dumps(parse_flow(flow['flow']))
247 def get_all_flows(modules=['ifm'], filter=[]):
249 return 'No modules specified'
261 table_list = list(range(0, 255))
263 table_list = list(set([table for module in modules for table in const.TABLE_MAP[module]]))
264 ##table_list = [214, 244]
265 of_nodes = dsg.get_inventory_config()
267 ifaces = dsg.get_config_interfaces()
268 ifstates = dsg.get_interface_states()
269 if 'l3vpn' in modules:
270 ifaces = ifaces or dsg.get_config_interfaces()
271 ifindexes = ifindexes or dsg.get_ifindexes()
272 fibentries = fibentries or dsg.get_fibentries_by_label()
273 vpnids = vpnids or dsg.get_vpnids()
274 vpninterfaces = vpninterfaces or dsg.get_vpninterfaces()
275 groups = groups or get_groups(of_nodes)
277 ifaces = ifaces or dsg.get_config_interfaces()
278 ifindexes = ifindexes or dsg.get_ifindexes()
279 einsts = einsts or dsg.get_elan_instances()
280 eifaces = eifaces or dsg.get_elan_interfaces()
281 if 'elan' in modules:
282 ifaces = ifaces or dsg.get_config_interfaces()
283 einsts = einsts or dsg.get_elan_instances()
284 eifaces = eifaces or dsg.get_elan_interfaces()
285 ifindexes = ifindexes or dsg.get_ifindexes()
287 groups = groups or get_groups(of_nodes)
288 ifaces = ifaces or dsg.get_config_interfaces()
289 ifstates = ifstates or dsg.get_interface_states()
290 ifindexes = ifindexes or dsg.get_ifindexes()
291 fibentries = fibentries or dsg.get_fibentries_by_label()
292 vpnids = vpnids or dsg.get_vpnids()
293 vpninterfaces = vpninterfaces or dsg.get_vpninterfaces()
294 einsts = einsts or dsg.get_elan_instances()
295 eifaces = eifaces or dsg.get_elan_interfaces()
297 for node in of_nodes.itervalues():
298 tables = [x for x in node[const.NODE_TABLE] if x['id'] in table_list]
300 for flow in table.get('flow', []):
303 flow_info['dpnid'] = utils.get_dpn_from_ofnodeid(node['id'])
304 flow_dict = fp.get_any_flow(flow, flow_info, groups,
305 ifaces, ifstates, ifindexes,
306 fibentries, vpnids, vpninterfaces,
308 if (flow_dict is not None and
309 utils.filter_flow(flow_dict, filter)):
310 flows.append(flow_dict)
314 def show_flows(modules=['ifm'], sort_by='table', filter_by=[]):
315 compute_map = get_dpn_host_mapping()
316 nports = dsg.get_neutron_ports()
317 for flow in utils.sort(get_all_flows(modules, filter_by), sort_by):
318 host = compute_map.get(flow.get('dpnid'), flow.get('dpnid'))
319 ip_list = get_ips_for_iface(nports, flow.get('ifname'))
321 flow['iface-ips'] = ip_list
322 result = 'Table:{},Host:{},FlowId:{}{}'.format(
323 flow['table'], host, flow['id'],
324 utils.show_optionals(flow))
326 print 'Flow:', json.dumps(parse_flow(flow['flow']))
329 def show_all_flows():
330 show_flows(modules=['all'])
333 def show_elan_flows():
334 compute_map = get_dpn_host_mapping()
335 for flow in utils.sort(get_all_flows(['elan']), 'id'):
336 host = compute_map.get(flow.get('dpnid'), flow.get('dpnid'))
337 result = 'MacHost:{}{},Table:{},FlowId:{},{},Flow:{}'.format(flow['id'][-17:],host,flow['table'],flow['id'],utils.show_optionals(flow),json.dumps(parse_flow(flow['flow'])))
339 #print 'Flow:', json.dumps(parse_flow(flow['flow']))
342 def get_matchstr(flow):
343 if flow and flow.get('flow') and flow.get('flow').get('match'):
344 return json.dumps(flow.get('flow').get('match', None))
347 def get_key_for_dup_detect(flow):
348 result = '{}:{}:{}'.format(flow.get('dpnid'), flow.get('table'), get_matchstr(flow))
352 def show_dup_flows():
353 mmac = dsg.get_mip_mac()
354 einsts = dsg.get_elan_instances()
355 flows = utils.sort(get_all_flows(['elan']), 'table')
356 matches = defaultdict(list)
357 compute_map = get_dpn_host_mapping()
359 dup_key = get_key_for_dup_detect(flow)
361 if matches and matches.get(dup_key):
362 matches[dup_key].append(flow)
364 matches[dup_key].append(flow)
365 for k, v in matches.iteritems():
367 dpnid = k.split(':')[0]
368 host = compute_map.get(dpnid, dpnid)
369 result = 'Host:{},FlowCount:{},MatchKey:{},ElanTag:{}'.format(host, len(v), k,v[0].get('elan-tag'))
371 for idx, flow in enumerate(v):
373 mac_addr = flow.get('dst-mac')
374 if mac_addr and mmac.get(mac_addr):
375 result = fp.is_correct_elan_flow(flow, mmac.get(mac_addr), einsts, host)
376 print ' {}Flow-{}:{}'.format(result, idx, json.dumps(parse_flow(flow.get('flow'))))
379 def show_learned_mac_flows():
380 nports = dsg.get_neutron_ports(key_field='mac-address')
381 flows = utils.sort(get_all_flows(['elan']), 'table')
382 compute_map = get_dpn_host_mapping()
383 for flow_info in flows:
384 flow = flow_info.get('flow')
385 dpnid = flow_info.get('dpnid')
386 host = compute_map.get(dpnid, dpnid)
387 if ((flow_info.get('table') == 50 and
388 flow.get('idle-timeout') == 300 and not
389 nports.get(flow_info.get('src-mac'))) or
390 (flow_info.get('table') == 51 and
391 not nports.get(flow_info.get('dst-mac')))):
392 result = 'Table:{},Host:{},FlowId:{}{}'.format(
393 flow_info.get('table'), host, flow.get('id'),
394 utils.show_optionals(flow_info))
396 print 'Flow:{}'.format(json.dumps(parse_flow(flow)))
399 def show_elan_instances():
400 insts = dsg.get_elan_instances()
404 def get_duplicate_ids():
406 for pool in dsg.get_idpools().itervalues():
408 for id_entry in pool.get('id-entries', []):
410 id_value = id_entry.get('id-value')[0]
411 id_key = id_entry.get('id-key')
412 if id_values and id_values.get(id_value, None):
413 key_list = id_values.get(id_value)
414 key_list.append(id_key)
415 id_info['id-value'] = id_value
416 id_info['id-keys'] = key_list
417 id_info['pool-name'] = pool.get('pool-name')
418 id_info['parent-pool-name'] = pool.get('parent-pool-name')
419 duplicate_ids[id_value] = id_info
421 id_values[id_value] = [id_key]
427 ports = dsg.get_neutron_ports()
429 for k,v in get_duplicate_ids().iteritems():
430 result = "Id:{},Keys:{}".format(k, json.dumps(v.get('id-keys')))
431 if v.get('pool-name'):
432 result = "{},Pool:{}".format(result, v.get('pool-name'))
433 if v.get('pool-name') == 'interfaces':
434 iface_ids.extend(v.get('id-keys'))
435 if v.get('parent-pool-name'):
436 result = "{},ParentPool:{}".format(result, v.get('parent-pool-name'))
438 print "\nNeutron Ports"
439 print "============="
441 port = ports.get(id, {})
442 print "Iface={}, NeutronPort={}".format(id, json.dumps(port))
445 def parse_flow(flow):
447 #hex(int(mask, 16) & int(data, 16))
449 utils.to_hex(flow, 'cookie')
451 for instruction in flow['instructions'].get('instruction', []):
452 if 'write-metadata' in instruction:
453 utils.to_hex(instruction['write-metadata'],'metadata')
454 utils.to_hex(instruction['write-metadata'],'metadata-mask')
455 if 'apply-actions' in instruction:
456 for action in instruction['apply-actions'].get('action', []):
457 if 'openflowplugin-extension-nicira-action:nx-reg-load' in action:
458 utils.to_hex(action['openflowplugin-extension-nicira-action:nx-reg-load'], 'value')
460 if 'metadata' in flow['match']:
461 metadata = flow['match']['metadata']
462 utils.to_hex(metadata,'metadata')
463 utils.to_hex(metadata,'metadata-mask')
465 for ofex in flow['match'].get('openflowplugin-extension-general:extension-list', []):
466 if ofex['extension-key'] == 'openflowplugin-extension-nicira-match:nxm-nx-reg6-key':
467 utils.to_hex(ofex['extension']['openflowplugin-extension-nicira-match:nxm-nx-reg'], 'value')
472 def get_data_path(res_type, data):
473 if res_type == 'bindings':
474 return 'interface-service-bindings:service-bindings/services-info/{}/{}'.format(data['interface-name'],data['service-mode'])
475 elif res_type == 'flows':
476 return 'opendaylight-inventory:nodes/node/openflow:{}/flow-node-inventory:table/{}/flow/{}'.format(data['dpnid'],data['table'],data['id'])
479 # Sample method that shows how to use
480 def show_all_tables():
481 of_nodes = dsg.get_inventory_config()
483 for node in of_nodes.itervalues():
484 for table in node[const.NODE_TABLE]:
485 if table.get('flow'):
486 tables.add(table['id'])
490 def show_all_groups():
491 of_nodes = dsg.get_inventory_config()
492 groups = get_groups(of_nodes)
494 for group_key in groups[dpn]:
495 print 'Dpn:', dpn, 'ID:', group_key, 'Group:', json.dumps(groups[dpn][group_key])
498 def analyze_trunks():
499 nports = dsg.get_neutron_ports()
500 ntrunks = dsg.get_neutron_trunks()
501 vpninterfaces = dsg.get_vpninterfaces()
502 ifaces = dsg.get_config_interfaces()
503 ifstates = dsg.get_interface_states()
505 for v in ntrunks.itervalues():
506 nport = nports.get(v.get('port-id'))
508 for subport in v.get('sub-ports'):
509 sport_id = subport.get('port-id')
510 snport = nports.get(sport_id)
511 svpniface = vpninterfaces.get(sport_id)
512 siface = ifaces.get(sport_id)
513 sifstate = ifstates.get(sport_id)
514 subport['SubNeutronPort'] = 'Correct' if snport else 'Wrong'
515 subport['SubVpnInterface'] = 'Correct' if svpniface else 'Wrong'
516 subport['ofport'] = utils.get_ofport_from_ncid(sifstate.get('lower-layer-if')[0])
518 vlan_mode = siface.get('odl-interface:l2vlan-mode')
519 parent_iface_id = siface.get('odl-interface:parent-interface')
520 if vlan_mode !='trunk-member':
521 subport['SubIface'] = 'WrongMode'
522 elif parent_iface_id !=v.get('port-id'):
523 subport['SubIface'] = 'WrongParent'
524 elif siface.get('odl-interface:vlan-id') !=subport.get('segmentation-id'):
525 subport['SubIface'] = 'WrongVlanId'
527 subport['SubIface'] = 'Correct'
529 subport['SubIface'] = 'Wrong'
530 s_subport = 'SegId:{},PortId:{},SubNeutronPort:{},SubIface:{},SubVpnIface:{}'.format(
531 subport.get('segmentation-id'),subport.get('port-id'),
532 subport.get('SubNeutronPort'),
533 subport.get('SubIface'),
534 subport.get('SubVpnInterface'))
535 s_subports.append(subport)
536 subport_dict[subport['port-id']] = subport
537 s_trunk = 'TrunkName:{},TrunkId:{},PortId:{},NeutronPort:{},SubPorts:{}'.format(
538 v.get('name'), v.get('uuid'), v.get('port-id'),
539 'Correct' if nport else 'Wrong', json.dumps(s_subports))
541 print '\n------------------------------------'
542 print 'Analyzing Flow status for SubPorts'
543 print '------------------------------------'
544 for flow in utils.sort(get_all_flows(['ifm'], ['vlanid']), 'ifname'):
545 subport = subport_dict.get(flow.get('ifname')) or None
546 vlanid = subport.get('segmentation-id') if subport else None
547 ofport = subport.get('ofport') if subport else None
549 if flow.get('ofport') and flow.get('ofport') != ofport:
550 flow_status = 'OfPort mismatch for SubPort:{} and Flow:{}'.format(subport, flow.get('flow'))
551 if flow.get('vlanid') and flow.get('vlanid') != vlanid:
552 flow_status = 'VlanId mismatch for SubPort:{} and Flow:{}'.format(subport, flow.get('flow'))
554 print 'SubPort:{},Table:{},FlowStatus:{}'.format(
555 subport.get('port-id'), flow.get('table'), flow_status)
562 options, args = utils.parse_args()
563 if options.callMethod:
565 eval(options.callMethod)(args[1:])
568 eval(options.callMethod)()
570 #print json.dumps(dsg.get_vpninterfaces())
572 #analyze_inventory('openflow:165862438671169',ifName='tunf94333cc491')
574 #show_stale_bindings()
575 analyze_interface([args[1]])
576 #og.print_flow_dict(og.get_ofctl_flows())
579 if __name__ == '__main__':