summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-06-27 11:12:05 +0200
committerChristian Poessinger <christian@poessinger.com>2021-06-27 11:14:12 +0200
commit09efa0550dd169e30a851513781b611dd84e9c79 (patch)
tree8420086b1b50ed5f60822222d3b83edf3c38cf55 /src
parentd34cd9572dd6285b92d3e0f8f80dc109a674c205 (diff)
downloadvyos-1x-09efa0550dd169e30a851513781b611dd84e9c79.tar.gz
vyos-1x-09efa0550dd169e30a851513781b611dd84e9c79.zip
op-mode: bond: T2546: implement "show interface bond * slaves" command
Add implementation with XML and Python.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/op_mode/show-bond.py92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/op_mode/show-bond.py b/src/op_mode/show-bond.py
new file mode 100755
index 000000000..edf7847fc
--- /dev/null
+++ b/src/op_mode/show-bond.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import jinja2
+
+from argparse import ArgumentParser
+from vyos.ifconfig import Section
+from vyos.ifconfig import BondIf
+from vyos.util import read_file
+
+from sys import exit
+
+parser = ArgumentParser()
+parser.add_argument("--slaves", action="store_true", help="Show LLDP neighbors on all interfaces")
+parser.add_argument("--interface", action="store", help="Show LLDP neighbors on specific interface")
+
+args = parser.parse_args()
+
+all_bonds = Section.interfaces('bonding')
+# we are not interested in any bond vlan interface
+all_bonds = [x for x in all_bonds if '.' not in x]
+
+TMPL_BRIEF = """Interface Mode State Link Slaves
+{% for interface in data %}
+{{ "%-12s" | format(interface.ifname) }} {{ "%-22s" | format(interface.mode) }} {{ "%-8s" | format(interface.admin_state) }} {{ "%-6s" | format(interface.oper_state) }} {{ interface.members | join(' ') }}
+{% endfor %}
+"""
+
+TMPL_INDIVIDUAL_BOND = """Interface RX: bytes packets TX: bytes packets
+{{ "%-16s" | format(data.ifname) }} {{ "%-10s" | format(data.rx_bytes) }} {{ "%-11s" | format(data.rx_packets) }} {{ "%-10s" | format(data.tx_bytes) }} {{ data.tx_packets }}
+{% for member in data.members if data.members is defined %}
+ {{ "%-12s" | format(member.ifname) }} {{ "%-10s" | format(member.rx_bytes) }} {{ "%-11s" | format(member.rx_packets) }} {{ "%-10s" | format(member.tx_bytes) }} {{ member.tx_packets }}
+{% endfor %}
+"""
+
+if args.slaves and args.interface:
+ exit('Can not use both --slaves and --interfaces option at the same time')
+ parser.print_help()
+
+elif args.slaves:
+ data = []
+ template = TMPL_BRIEF
+ for bond in all_bonds:
+ tmp = BondIf(bond)
+ cfg_dict = {}
+ cfg_dict['ifname'] = bond
+ cfg_dict['mode'] = tmp.get_mode()
+ cfg_dict['admin_state'] = tmp.get_admin_state()
+ cfg_dict['oper_state'] = tmp.operational.get_state()
+ cfg_dict['members'] = tmp.get_slaves()
+ data.append(cfg_dict)
+
+elif args.interface:
+ template = TMPL_INDIVIDUAL_BOND
+ data = {}
+ data['ifname'] = args.interface
+ data['rx_bytes'] = read_file(f'/sys/class/net/{args.interface}/statistics/rx_bytes')
+ data['rx_packets'] = read_file(f'/sys/class/net/{args.interface}/statistics/rx_packets')
+ data['tx_bytes'] = read_file(f'/sys/class/net/{args.interface}/statistics/tx_bytes')
+ data['tx_packets'] = read_file(f'/sys/class/net/{args.interface}/statistics/tx_packets')
+
+ # each bond member interface has its own statistics
+ data['members'] = []
+ for member in BondIf(args.interface).get_slaves():
+ tmp = {}
+ tmp['ifname'] = member
+ tmp['rx_bytes'] = read_file(f'/sys/class/net/{member}/statistics/rx_bytes')
+ tmp['rx_packets'] = read_file(f'/sys/class/net/{member}/statistics/rx_packets')
+ tmp['tx_bytes'] = read_file(f'/sys/class/net/{member}/statistics/tx_bytes')
+ tmp['tx_packets'] = read_file(f'/sys/class/net/{member}/statistics/tx_packets')
+ data['members'].append(tmp)
+
+else:
+ parser.print_help()
+ exit(1)
+
+tmpl = jinja2.Template(template, trim_blocks=True)
+config_text = tmpl.render(data=data)
+print(config_text)