blob: 6853dabc0336afa1f4b5dbc7067eadf13f1ca8cb [file] [log] [blame]
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +01001import re
2import sys
3import subprocess
4import json
5
6
7def shell(command):
8 _ps = subprocess.Popen(
9 command.split(),
10 stdout=subprocess.PIPE
11 ).communicate()[0].decode()
12
13 return _ps
14
15
16def cut_option(_param, _options_list):
17 _option = "n/a"
18 _result_list = []
19 if _param in _options_list:
20 _index = _options_list.index(_param)
21 _option = _options_list[_index+1]
22 _l1 = _options_list[:_index]
23 _l2 = _options_list[_index+2:]
24 _result_list = _l1 + _l2
25 else:
26 _result_list = _options_list
27 return _option, _result_list
28
29
Alex Savatieiev0137dad2019-01-25 16:18:42 +010030def get_linked_devices(if_name):
31 if '@' in if_name:
32 _name = if_name[:if_name.index('@')]
33 else:
34 _name = if_name
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010035 # identify device type
36 _dev_link_path = shell('readlink /sys/class/net/{}'.format(_name))
37 _type = "unknown"
38 if len(_dev_link_path) > 0:
39 _tmp = _dev_link_path.split('/')
40 _tmp = _tmp[_tmp.index("devices") + 1]
41 if _tmp.startswith("pci"):
42 _type = "physical"
43 elif _tmp.startswith("virtual"):
44 _type = "virtual"
45
46 # get linked devices if any
Alex Savatieiev0137dad2019-01-25 16:18:42 +010047 _links = shell(
48 "find /sys/class/net/{}/ -type l".format(_name)
49 )
50 # there can be only one parent device
51 _lower = None
52 # can be more than one child device
53 _upper = None
54 for line in _links.splitlines():
55 _line = line.rsplit('/', 1)[1]
56 if _line.startswith("upper_"):
57 _upper = _line[6:]
58 elif _line.startswith("lower_"):
59 if not _lower:
60 _lower = []
61 _lower.append(_line[6:])
62
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010063 return _lower, _upper, _type
Alex Savatieiev0137dad2019-01-25 16:18:42 +010064
65
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010066def get_ifs_data():
67 _ifs_raw = shell('ip a')
68
69 if_start = re.compile("^[0-9]+: .*: \<.*\> .*$")
Alex Savatieiev0137dad2019-01-25 16:18:42 +010070 if_link = re.compile("^\s{4}link\/ether\ .*$")
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010071 if_ipv4 = re.compile("^\s{4}inet\ .*$")
72
73 _ifs = {}
74 _if_name = None
75 for line in _ifs_raw.splitlines():
76 _if_data = {}
77 if if_start.match(line):
78 _tmp = line.split(':')
79 _if_name = _tmp[1].strip()
80 _if_options = _tmp[2].strip().split(' ')
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010081 _lower, _upper, _type = get_linked_devices(_if_name)
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010082 _if_data['order'] = _tmp[0]
83 _if_data['mtu'], _if_options = cut_option("mtu", _if_options)
84 _if_data['qlen'], _if_options = cut_option("qlen", _if_options)
85 _if_data['state'], _if_options = cut_option("state", _if_options)
86 _if_data['other'] = _if_options
87 _if_data['ipv4'] = {}
Alex Savatieiev0137dad2019-01-25 16:18:42 +010088 _if_data['mac'] = {}
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010089 _if_data['type'] = _type
Alex Savatieiev0137dad2019-01-25 16:18:42 +010090 _if_data['upper'] = _upper
91 _if_data['lower'] = _lower
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010092 _ifs[_if_name] = _if_data
Alex Savatieiev0137dad2019-01-25 16:18:42 +010093 elif if_link.match(line):
94 if _if_name is None:
95 continue
96 else:
97 _tmp = line.strip().split(' ', 2)
98 _mac_addr = _tmp[1]
99 _options = _tmp[2].split(' ')
100 _brd, _options = cut_option("brd", _options)
101 _ifs[_if_name]['mac'][_mac_addr] = {}
102 _ifs[_if_name]['mac'][_mac_addr]['brd'] = _brd
103 _ifs[_if_name]['mac'][_mac_addr]['other'] = _options
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +0100104 elif if_ipv4.match(line):
105 if _if_name is None:
106 continue
107 else:
108 _tmp = line.strip().split(' ', 2)
109 _ip = _tmp[1]
110 _options = _tmp[2].split(' ')
111 _brd, _options = cut_option("brd", _options)
112 # TODO: Parse other options, mask, brd, etc...
113 _ifs[_if_name]['ipv4'][_ip] = {}
114 _ifs[_if_name]['ipv4'][_ip]['brd'] = _brd
115 _ifs[_if_name]['ipv4'][_ip]['other'] = _options
116
117 return _ifs
118
119
120ifs_data = get_ifs_data()
121
Alex Savatieiev0137dad2019-01-25 16:18:42 +0100122if len(sys.argv) > 1 and sys.argv[1] == 'json':
123 sys.stdout.write(json.dumps(ifs_data))
124else:
125 _ifs = sorted(ifs_data.keys())
126 _ifs.remove("lo")
127 for _idx in range(len(_ifs)):
128 _linked = ""
129 if ifs_data[_ifs[_idx]]['lower']:
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +0100130 _linked += "lower:{} ".format(
Alex Savatieiev0137dad2019-01-25 16:18:42 +0100131 ','.join(ifs_data[_ifs[_idx]]['lower'])
132 )
133 if ifs_data[_ifs[_idx]]['upper']:
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +0100134 _linked += "upper:{} ".format(ifs_data[_ifs[_idx]]['upper'])
135 _linked = _linked.strip()
136 print("{0:8} {1:30} {2:18} {3:19} {4:5} {5:4} {6}".format(
137 ifs_data[_ifs[_idx]]['type'],
Alex Savatieiev0137dad2019-01-25 16:18:42 +0100138 _ifs[_idx],
139 ",".join(ifs_data[_ifs[_idx]]['mac'].keys()),
140 ",".join(ifs_data[_ifs[_idx]]['ipv4'].keys()),
141 ifs_data[_ifs[_idx]]['mtu'],
142 ifs_data[_ifs[_idx]]['state'],
143 _linked
144 ))