#!/usr/bin/env python3 # # Copyright (C) 2023 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/>. # File: show_igmpproxy.py # Purpose: # Display istatistics from IPv4 IGMP proxy. # Used by the "run show ip multicast" command tree. import ipaddress import json import socket import sys import tabulate import vyos.config import vyos.opmode from vyos.util import bytes_to_human, print_error def _is_configured(): """Check if IGMP proxy is configured""" return vyos.config.Config().exists_effective('protocols igmp-proxy') def _is_running(): """Check if IGMP proxy is currently running""" return not vyos.util.run('ps -C igmpproxy') def _kernel_to_ip(addr): """ Convert any given address from Linux kernel to a proper, IPv4 address using the correct host byte order. """ # Convert from hex 'FE000A0A' to decimal '4261415434' addr = int(addr, 16) # Kernel ABI _always_ uses network byte order. addr = socket.ntohl(addr) return str(ipaddress.IPv4Address(addr)) def _process_mr_vif(): """Read rows from /proc/net/ip_mr_vif into dicts.""" result = [] with open('/proc/net/ip_mr_vif', 'r') as f: next(f) for line in f: result.append({ 'Interface': line.split()[1], 'PktsIn' : int(line.split()[3]), 'PktsOut' : int(line.split()[5]), 'BytesIn' : int(line.split()[2]), 'BytesOut' : int(line.split()[4]), 'Local' : _kernel_to_ip(line.split()[7]), }) return result def show_interface(raw: bool): if data := _process_mr_vif(): if raw: # Make the interface name the key for each row. table = {} for v in data: table[v.pop('Interface')] = v return json.loads(json.dumps(table)) # Make byte values human-readable for the table. arr = [] for x in data: arr.append({k: bytes_to_human(v) if k.startswith('Bytes') \ else v for k, v in x.items()}) return tabulate.tabulate(arr, headers='keys') if not _is_configured(): print_error('IGMP proxy is not configured.') sys.exit(0) if not _is_running(): print_error('IGMP proxy is not running.') sys.exit(0) if __name__ == "__main__": try: res = vyos.opmode.run(sys.modules[__name__]) if res: print(res) except (ValueError, vyos.opmode.Error) as e: print_error(e) sys.exit(1)