blob: 3b7a8e51efbb756e546cf5c01f90077c7f935049 [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_"):
Alex Savatieievbd256e82019-01-25 18:27:01 +010057 if not _upper:
58 _upper = []
59 _upper.append(_line[6:])
Alex Savatieiev0137dad2019-01-25 16:18:42 +010060 elif _line.startswith("lower_"):
61 if not _lower:
62 _lower = []
63 _lower.append(_line[6:])
64
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010065 return _lower, _upper, _type
Alex Savatieiev0137dad2019-01-25 16:18:42 +010066
67
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010068def get_ifs_data():
69 _ifs_raw = shell('ip a')
70
71 if_start = re.compile("^[0-9]+: .*: \<.*\> .*$")
Alex Savatieiev0137dad2019-01-25 16:18:42 +010072 if_link = re.compile("^\s{4}link\/ether\ .*$")
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010073 if_ipv4 = re.compile("^\s{4}inet\ .*$")
74
75 _ifs = {}
76 _if_name = None
77 for line in _ifs_raw.splitlines():
78 _if_data = {}
79 if if_start.match(line):
80 _tmp = line.split(':')
81 _if_name = _tmp[1].strip()
82 _if_options = _tmp[2].strip().split(' ')
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010083 _lower, _upper, _type = get_linked_devices(_if_name)
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010084 _if_data['order'] = _tmp[0]
85 _if_data['mtu'], _if_options = cut_option("mtu", _if_options)
86 _if_data['qlen'], _if_options = cut_option("qlen", _if_options)
87 _if_data['state'], _if_options = cut_option("state", _if_options)
88 _if_data['other'] = _if_options
89 _if_data['ipv4'] = {}
Alex Savatieiev0137dad2019-01-25 16:18:42 +010090 _if_data['mac'] = {}
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +010091 _if_data['type'] = _type
Alex Savatieiev0137dad2019-01-25 16:18:42 +010092 _if_data['upper'] = _upper
93 _if_data['lower'] = _lower
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +010094 _ifs[_if_name] = _if_data
Alex Savatieiev0137dad2019-01-25 16:18:42 +010095 elif if_link.match(line):
96 if _if_name is None:
97 continue
98 else:
99 _tmp = line.strip().split(' ', 2)
100 _mac_addr = _tmp[1]
101 _options = _tmp[2].split(' ')
102 _brd, _options = cut_option("brd", _options)
103 _ifs[_if_name]['mac'][_mac_addr] = {}
104 _ifs[_if_name]['mac'][_mac_addr]['brd'] = _brd
105 _ifs[_if_name]['mac'][_mac_addr]['other'] = _options
Oleksandr Savatieievfb9f9432018-11-23 17:39:12 +0100106 elif if_ipv4.match(line):
107 if _if_name is None:
108 continue
109 else:
110 _tmp = line.strip().split(' ', 2)
111 _ip = _tmp[1]
112 _options = _tmp[2].split(' ')
113 _brd, _options = cut_option("brd", _options)
114 # TODO: Parse other options, mask, brd, etc...
115 _ifs[_if_name]['ipv4'][_ip] = {}
116 _ifs[_if_name]['ipv4'][_ip]['brd'] = _brd
117 _ifs[_if_name]['ipv4'][_ip]['other'] = _options
118
119 return _ifs
120
121
122ifs_data = get_ifs_data()
123
Alex Savatieiev0137dad2019-01-25 16:18:42 +0100124if len(sys.argv) > 1 and sys.argv[1] == 'json':
125 sys.stdout.write(json.dumps(ifs_data))
126else:
127 _ifs = sorted(ifs_data.keys())
128 _ifs.remove("lo")
129 for _idx in range(len(_ifs)):
130 _linked = ""
131 if ifs_data[_ifs[_idx]]['lower']:
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +0100132 _linked += "lower:{} ".format(
Alex Savatieiev0137dad2019-01-25 16:18:42 +0100133 ','.join(ifs_data[_ifs[_idx]]['lower'])
134 )
135 if ifs_data[_ifs[_idx]]['upper']:
Alex Savatieievbd256e82019-01-25 18:27:01 +0100136 _linked += "upper:{} ".format(
137 ','.join(ifs_data[_ifs[_idx]]['upper'])
138 )
Alex Savatieiev5d1eebb2019-01-25 18:15:36 +0100139 _linked = _linked.strip()
140 print("{0:8} {1:30} {2:18} {3:19} {4:5} {5:4} {6}".format(
141 ifs_data[_ifs[_idx]]['type'],
Alex Savatieiev0137dad2019-01-25 16:18:42 +0100142 _ifs[_idx],
143 ",".join(ifs_data[_ifs[_idx]]['mac'].keys()),
144 ",".join(ifs_data[_ifs[_idx]]['ipv4'].keys()),
145 ifs_data[_ifs[_idx]]['mtu'],
146 ifs_data[_ifs[_idx]]['state'],
147 _linked
148 ))