Page MenuHomeVyOS Platform

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/src/op_mode/show_interfaces.py b/src/op_mode/show_interfaces.py
index 256c86d2a..5375a8406 100755
--- a/src/op_mode/show_interfaces.py
+++ b/src/op_mode/show_interfaces.py
@@ -1,314 +1,311 @@
#!/usr/bin/env python3
# Copyright 2017, 2019 VyOS maintainers and contributors <[email protected]>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
import os
import re
import sys
import glob
import datetime
import argparse
import netifaces
from vyos.ifconfig import Section
from vyos.ifconfig import Interface
from vyos.ifconfig import VRRP
from vyos.util import cmd
# interfaces = Sections.reserved()
interfaces = ['eno', 'ens', 'enp', 'enx', 'eth', 'vmnet', 'lo', 'tun', 'wan', 'pppoe', 'pppoa', 'adsl']
glob_ifnames = '/sys/class/net/({})*'.format('|'.join(interfaces))
actions = {}
def register(name):
"""
Decorator to register a function into actions with a name.
`actions[name]' can be used to call the registered functions.
We wrap each function in a SIGPIPE handler as all registered functions
can be subject to a broken pipe if there are a lot of interfaces.
"""
def _register(function):
def handled_function(*args, **kwargs):
try:
function(*args, **kwargs)
except BrokenPipeError:
# Flush output to /dev/null and bail out.
os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())
sys.exit(1)
actions[name] = handled_function
return handled_function
return _register
def filtered_interfaces(ifnames, iftypes, vif, vrrp):
"""
get all the interfaces from the OS and returns them
ifnames can be used to filter which interfaces should be considered
ifnames: a list of interfaces names to consider, empty do not filter
return an instance of the interface class
"""
allnames = Section.interfaces()
vrrp_interfaces = VRRP.active_interfaces() if vrrp else []
for ifname in allnames:
if ifnames and ifname not in ifnames:
continue
- # return the class which can handle this interface name
- klass = Section.klass(ifname)
- # connect to the interface
- interface = klass(ifname, create=False, debug=False)
+ interface = Interface(ifname)
if iftypes and interface.definition['section'] not in iftypes:
continue
if vif and not '.' in ifname:
continue
if vrrp and ifname not in vrrp_interfaces:
continue
yield interface
def split_text(text, used=0):
"""
take a string and attempt to split it to fit with the width of the screen
text: the string to split
used: number of characted already used in the screen
"""
returned = cmd('stty size')
if len(returned) == 2:
rows, columns = [int(_) for _ in returned]
else:
rows, columns = (40, 80)
desc_len = columns - used
line = ''
for word in text.split():
if len(line) + len(word) < desc_len:
line = f'{line} {word}'
continue
if line:
yield line[1:]
else:
line = f'{line} {word}'
yield line[1:]
def get_vrrp_intf():
return [intf for intf in Section.interfaces() if intf.is_vrrp()]
def get_counter_val(clear, now):
"""
attempt to correct a counter if it wrapped, copied from perl
clear: previous counter
now: the current counter
"""
# This function has to deal with both 32 and 64 bit counters
if clear == 0:
return now
# device is using 64 bit values assume they never wrap
value = now - clear
if (now >> 32) != 0:
return value
# The counter has rolled. If the counter has rolled
# multiple times since the clear value, then this math
# is meaningless.
if (value < 0):
value = (4294967296 - clear) + now
return value
@register('help')
def usage(*args):
print(f"Usage: {sys.argv[0]} [intf=NAME|intf-type=TYPE|vif|vrrp] action=ACTION")
print(f" NAME = " + ' | '.join(Section.interfaces()))
print(f" TYPE = " + ' | '.join(Section.sections()))
print(f" ACTION = " + ' | '.join(actions))
sys.exit(1)
@register('allowed')
def run_allowed(**kwarg):
sys.stdout.write(' '.join(Section.interfaces()))
def pppoe(ifname):
out = cmd(f'ps -C pppd -f')
if ifname in out:
return 'C'
elif ifname in [_.split('/')[-1] for _ in glob.glob('/etc/ppp/peers/pppoe*')]:
return 'D'
return ''
@register('show')
def run_show_intf(ifnames, iftypes, vif, vrrp):
handled = []
for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp):
handled.append(interface.ifname)
cache = interface.operational.load_counters()
out = cmd(f'ip addr show {interface.ifname}')
out = re.sub(f'^\d+:\s+','',out)
if re.search("link/tunnel6", out):
tunnel = cmd(f'ip -6 tun show {interface.ifname}')
# tun0: ip/ipv6 remote ::2 local ::1 encaplimit 4 hoplimit 64 tclass inherit flowlabel inherit (flowinfo 0x00000000)
tunnel = re.sub('.*encap', 'encap', tunnel)
out = re.sub('(\n\s+)(link/tunnel6)', f'\g<1>{tunnel}\g<1>\g<2>', out)
print(out)
timestamp = int(cache.get('timestamp', 0))
if timestamp:
when = interface.operational.strtime(timestamp)
print(f' Last clear: {when}')
description = interface.get_alias()
if description:
print(f' Description: {description}')
print()
print(interface.operational.formated_stats())
for ifname in ifnames:
if ifname not in handled and ifname.startswith('pppoe'):
state = pppoe(ifname)
if not state:
continue
string = {
'C': 'Coming up',
'D': 'Link down',
}[state]
print('{}: {}'.format(ifname, string))
@register('show-brief')
def run_show_intf_brief(ifnames, iftypes, vif, vrrp):
format1 = '%-16s %-33s %-4s %s'
format2 = '%-16s %s'
print('Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down')
print(format1 % ("Interface", "IP Address", "S/L", "Description"))
print(format1 % ("---------", "----------", "---", "-----------"))
handled = []
for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp):
handled.append(interface.ifname)
oper_state = interface.operational.get_state()
admin_state = interface.get_admin_state()
intf = [interface.ifname,]
oper = ['u', ] if oper_state in ('up', 'unknown') else ['D', ]
admin = ['u', ] if admin_state in ('up', 'unknown') else ['A', ]
addrs = [_ for _ in interface.get_addr() if not _.startswith('fe80::')] or ['-', ]
descs = list(split_text(interface.get_alias(),0))
while intf or oper or admin or addrs or descs:
i = intf.pop(0) if intf else ''
a = addrs.pop(0) if addrs else ''
d = descs.pop(0) if descs else ''
s = [admin.pop(0)] if admin else []
l = [oper.pop(0)] if oper else []
if len(a) < 33:
print(format1 % (i, a, '/'.join(s+l), d))
else:
print(format2 % (i, a))
print(format1 % ('', '', '/'.join(s+l), d))
for ifname in ifnames:
if ifname not in handled and ifname.startswith('pppoe'):
state = pppoe(ifname)
if not state:
continue
string = {
'C': 'u/D',
'D': 'A/D',
}[state]
print(format1 % (ifname, '', string, ''))
@register('show-count')
def run_show_counters(ifnames, iftypes, vif, vrrp):
formating = '%-12s %10s %10s %10s %10s'
print(formating % ('Interface', 'Rx Packets', 'Rx Bytes', 'Tx Packets', 'Tx Bytes'))
for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp):
oper = interface.operational.get_state()
if oper not in ('up','unknown'):
continue
stats = interface.operational.get_stats()
cache = interface.operational.load_counters()
print(formating % (
interface.ifname,
get_counter_val(cache['rx_packets'], stats['rx_packets']),
get_counter_val(cache['rx_bytes'], stats['rx_bytes']),
get_counter_val(cache['tx_packets'], stats['tx_packets']),
get_counter_val(cache['tx_bytes'], stats['tx_bytes']),
))
@register('clear')
def run_clear_intf(ifnames, iftypes, vif, vrrp):
for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp):
print(f'Clearing {interface.ifname}')
interface.operational.clear_counters()
@register('reset')
def run_reset_intf(ifnames, iftypes, vif, vrrp):
for interface in filtered_interfaces(ifnames, iftypes, vif, vrrp):
interface.operational.reset_counters()
if __name__ == '__main__':
parser = argparse.ArgumentParser(add_help=False, description='Show interface information')
parser.add_argument('--intf', action="store", type=str, default='', help='only show the specified interface(s)')
parser.add_argument('--intf-type', action="store", type=str, default='', help='only show the specified interface type')
parser.add_argument('--action', action="store", type=str, default='show', help='action to perform')
parser.add_argument('--vif', action='store_true', default=False, help="only show vif interfaces")
parser.add_argument('--vrrp', action='store_true', default=False, help="only show vrrp interfaces")
parser.add_argument('--help', action='store_true', default=False, help="show help")
args = parser.parse_args()
def missing(*args):
print('Invalid action [{args.action}]')
usage()
actions.get(args.action, missing)(
[_ for _ in args.intf.split(' ') if _],
[_ for _ in args.intf_type.split(' ') if _],
args.vif,
args.vrrp
)

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 31, 11:19 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
893525
Default Alt Text
(10 KB)

Event Timeline