diff --git a/board/aarch64/linux_defconfig b/board/aarch64/linux_defconfig index 2b29394ca..054a13d6e 100644 --- a/board/aarch64/linux_defconfig +++ b/board/aarch64/linux_defconfig @@ -539,6 +539,8 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=20 CONFIG_DETECT_HUNG_TASK=y # CONFIG_SCHED_DEBUG is not set # CONFIG_RCU_TRACE is not set diff --git a/board/x86_64/linux_defconfig b/board/x86_64/linux_defconfig index 6662bca0e..68ff214c7 100644 --- a/board/x86_64/linux_defconfig +++ b/board/x86_64/linux_defconfig @@ -260,6 +260,8 @@ CONFIG_CRYPTO_GCM=y CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=20 CONFIG_DETECT_HUNG_TASK=y CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y # CONFIG_FTRACE is not set diff --git a/configs/r2s_defconfig b/configs/r2s_defconfig index 9fdd0be86..124291a23 100644 --- a/configs/r2s_defconfig +++ b/configs/r2s_defconfig @@ -14,8 +14,8 @@ BR2_TARGET_GENERIC_ISSUE="Infix by KernelKit" BR2_INIT_FINIT=y BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y BR2_ROOTFS_DEVICE_TABLE="system/device_table.txt ${BR2_EXTERNAL_INFIX_PATH}/board/common/xattrs" -# BR2_TARGET_ENABLE_ROOT_LOGIN is not set BR2_ROOTFS_MERGED_USR=y +# BR2_TARGET_ENABLE_ROOT_LOGIN is not set BR2_SYSTEM_BIN_SH_BASH=y BR2_TARGET_GENERIC_GETTY_PORT="@console" BR2_TARGET_GENERIC_GETTY_TERM="xterm" @@ -71,7 +71,9 @@ BR2_PACKAGE_UBOOT_TOOLS_FIT_CHECK_SIGN=y BR2_PACKAGE_UBOOT_TOOLS_MKENVIMAGE=y BR2_PACKAGE_PYTHON3=y BR2_PACKAGE_PYTHON_GUNICORN=y +BR2_PACKAGE_LIBSSH_OPENSSL=y BR2_PACKAGE_LIBSSH2=y +BR2_PACKAGE_LIBSSH2_OPENSSL=y BR2_PACKAGE_LIBXCRYPT=y BR2_PACKAGE_LIBOPENSSL_BIN=y BR2_PACKAGE_LIBINPUT=y @@ -173,7 +175,6 @@ INFIX_HOME="https://github.com/kernelkit/infix/" INFIX_DOC="https://github.com/kernelkit/infix/tree/main/doc" INFIX_SUPPORT="mailto:kernelkit@googlegroups.com" BR2_PACKAGE_CONFD=y -# BR2_PACKAGE_CONFD_TEST_MODE is not set BR2_PACKAGE_EXECD=y BR2_PACKAGE_GENCERT=y BR2_PACKAGE_STATD=y diff --git a/src/confd/yang/infix-if-container.yang b/src/confd/yang/infix-if-container.yang index 56d52704e..425156736 100644 --- a/src/confd/yang/infix-if-container.yang +++ b/src/confd/yang/infix-if-container.yang @@ -23,6 +23,10 @@ submodule infix-if-container { Ensures a container interface can never be a bridge port, or LAG member, at the same time."; + revision 2024-10-29 { + description "Add read only container list to container-network"; + reference "internal"; + } revision 2024-01-15 { description "Initial revision."; reference "internal"; @@ -64,7 +68,11 @@ submodule infix-if-container { base container-network; } } - + leaf-list containers { + type string; + config false; + description "List of containers using this interface"; + } list subnet { description "Static IP ranges to hand out addresses to containers from. diff --git a/src/confd/yang/infix-if-container@2024-01-15.yang b/src/confd/yang/infix-if-container@2024-10-29.yang similarity index 100% rename from src/confd/yang/infix-if-container@2024-01-15.yang rename to src/confd/yang/infix-if-container@2024-10-29.yang diff --git a/src/klish-plugin-infix/xml/infix.xml b/src/klish-plugin-infix/xml/infix.xml index 17899fec0..abbb6cb25 100644 --- a/src/klish-plugin-infix/xml/infix.xml +++ b/src/klish-plugin-infix/xml/infix.xml @@ -361,7 +361,7 @@ if [ -n "$KLISH_PARAM_name" ]; then sysrepocfg -f json -X -d operational -x \ - "/ietf-interfaces:interfaces/interface[name='$KLISH_PARAM_name']" | \ + "/ietf-interfaces:interfaces/interface[name=\"$KLISH_PARAM_name\"]" | \ /usr/libexec/statd/cli-pretty "show-interfaces" -n "$KLISH_PARAM_name" else sysrepocfg -f json -X -d operational -m ietf-interfaces | \ diff --git a/src/statd/python/cli_pretty/cli_pretty.py b/src/statd/python/cli_pretty/cli_pretty.py index 12635f393..e8a370cc0 100755 --- a/src/statd/python/cli_pretty/cli_pretty.py +++ b/src/statd/python/cli_pretty/cli_pretty.py @@ -80,6 +80,10 @@ def yellow(txt): def underline(txt): return Decore.decorate("4", txt, "24") + @staticmethod + def gray_bg(txt): + return Decore.decorate("100", txt) + def datetime_now(): if UNIT_TEST: return datetime(2023, 1, 1, 12, 0, 0, tzinfo=timezone.utc) @@ -273,6 +277,7 @@ def __init__(self, data): self.bridge = get_json_data('', self.data, 'infix-interfaces:bridge-port', 'bridge') self.pvid = get_json_data('', self.data, 'infix-interfaces:bridge-port', 'pvid') self.stp_state = get_json_data('', self.data, 'infix-interfaces:bridge-port', 'stp-state') + self.containers = get_json_data('', self.data, 'infix-interfaces:container-network', 'containers') if data.get('statistics'): self.in_octets = data.get('statistics').get('in-octets', '') @@ -302,6 +307,10 @@ def __init__(self, data): def is_vlan(self): return self.type == "infix-if-type:vlan" + def is_in_container(self): + # Return negative if cointainer isn't set or is an empty list + return getattr(self, 'containers', None) + def is_bridge(self): return self.type == "infix-if-type:bridge" @@ -436,7 +445,18 @@ def pr_vlan(self, _ifaces): parent.pr_name(pipe='└ ') parent.pr_proto_eth() + def pr_container(self): + row = f"{self.name:<{Pad.iface}}" + row += f"{'container':<{Pad.proto}}" + row += f"{'':<{Pad.state}}" + row += f"{', ' . join(self.containers):<{Pad.data}}" + + print(Decore.gray_bg(row)) + def pr_iface(self): + if self.is_in_container(): + print(Decore.gray_bg(f"{'owned by container':<{20}}: {', ' . join(self.containers)}")) + print(f"{'name':<{20}}: {self.name}") print(f"{'index':<{20}}: {self.index}") if self.mtu: @@ -564,6 +584,10 @@ def pr_interface_list(json): if iface.name == "lo": continue + if iface.is_in_container(): + iface.pr_container() + continue + if iface.is_bridge(): iface.pr_bridge(ifaces) continue diff --git a/src/statd/python/yanger/yanger.py b/src/statd/python/yanger/yanger.py index 1b9654023..35bee36f9 100755 --- a/src/statd/python/yanger/yanger.py +++ b/src/statd/python/yanger/yanger.py @@ -629,18 +629,52 @@ def get_brport_multicast(ifname): def get_ip_link(): """Fetch interface link information from kernel""" return run_json_cmd(['ip', '-s', '-d', '-j', 'link', 'show'], - f"ip-link-show.json") + "ip-link-show.json") +def netns_get_ip_link(netns): + """Fetch interface link information from within a network namespace""" + return run_json_cmd(['ip', 'netns', 'exec', netns, 'ip', '-s', '-d', '-j', 'link', 'show'], + f"netns-{netns}-ip-link-show.json") def get_ip_addr(): """Fetch interface address information from kernel""" return run_json_cmd(['ip', '-j', 'addr', 'show'], - f"ip-addr-show.json") + "ip-addr-show.json") + +def netns_get_ip_addr(netns): + """Fetch interface address information from within a network namespace""" + return run_json_cmd(['ip', 'netns', 'exec', netns, 'ip', '-j', 'addr', 'show'], + f"netns-{netns}-ip-addr-show.json") + +def get_netns_list(): + """Fetch a list of network namespaces""" + return run_json_cmd(['ip', '-j', 'netns', 'list'], + "netns-list.json") + +def netns_find_ifname(ifname): + """Find which network namespace owns ifname (if any)""" + for netns in get_netns_list(): + for iface in netns_get_ip_link(netns['name']): + if 'ifalias' in iface and iface['ifalias'] == ifname: + return netns['name'] + return None + +def netns_ifindex_to_ifname(ifindex): + """Look through all network namespaces for an interface index and return its name""" + for netns in get_netns_list(): + for iface in netns_get_ip_link(netns['name']): + if iface['ifindex'] == ifindex: + if 'ifalias' in iface: + return iface['ifalias'] + if 'ifname' in iface: + return iface['ifname'] + return None + return None def add_ip_link(ifname, iface_in, iface_out): if 'ifname' in iface_in: - iface_out['name'] = iface_in['ifname'] + iface_out['name'] = ifname if 'ifindex' in iface_in: iface_out['if-index'] = iface_in['ifindex'] @@ -664,17 +698,17 @@ def add_ip_link(ifname, iface_in, iface_out): multicast = get_brport_multicast(ifname) insert(iface_out, "infix-interfaces:bridge-port", "multicast", multicast) - if 'link' in iface_in and not iface_is_dsa(iface_in): - insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", iface_in['link']) + if not iface_is_dsa(iface_in): + if 'link' in iface_in: + insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", iface_in['link']) + elif 'link_index' in iface_in: + # 'link_index' is the only reference we have if the link iface is in a namespace + lower = netns_ifindex_to_ifname(iface_in['link_index']) + if lower: + insert(iface_out, "infix-interfaces:vlan", "lower-layer-if", lower) if 'flags' in iface_in: - admin_xlate = { - "UP": "up", - "DOWN": "down" - } - - admin_status = admin_xlate.get("UP" if "UP" in iface_in['flags'] else "DOWN", "testing") - iface_out['admin-status'] = admin_status + iface_out['admin-status'] = "up" if "UP" in iface_in['flags'] else "down" if 'operstate' in iface_in: xlate = { @@ -891,6 +925,39 @@ def add_mdb_to_bridge(brname, iface_out, mc_status): insert(iface_out, "infix-interfaces:bridge", "multicast", multicast) insert(iface_out, "infix-interfaces:bridge", "multicast-filters", "multicast-filter", multicast_filters) +def add_container_ifaces(yang_ifaces): + """Add all podman interfaces with limited data""" + interfaces={} + try: + containers = run_json_cmd(['podman', 'ps', '--format', 'json'], "podman-ps.json", default=[]) + except Exception as e: + logging.error(f"Error, unable to run podman: {e}") + return + + for container in containers: + name = container.get('Names', ['Unknown'])[0] + networks = container.get('Networks', []) + + for network in networks: + if not network in interfaces: + interfaces[network] = [] + if name not in interfaces[network]: + interfaces[network].append(name) + + for ifname, containers in interfaces.items(): + iface_out = {} + iface_out['name'] = ifname + iface_out['type'] = "infix-if-type:other" # Fallback + insert(iface_out, "infix-interfaces:container-network", "containers", containers) + + netns = netns_find_ifname(ifname) + if netns is not None: + ip_link_data = netns_get_ip_link(netns) + ip_link_data = next((d for d in ip_link_data if d.get('ifalias') == ifname), None) + add_ip_link(ifname, ip_link_data, iface_out) + + yang_ifaces.append(iface_out) + # Helper function to add tagged/untagged interfaces to a vlan dict in a list def _add_vlan_iface(vlans, multicast_filter, multicast, vid, key, val): for d in vlans: @@ -968,6 +1035,8 @@ def add_interface(ifname, yang_ifaces): addr = next((d for d in ip_addr_data if d.get('ifname') == link["ifname"]), None) _add_interface(link["ifname"], link, addr, yang_ifaces) + add_container_ifaces(yang_ifaces) + def main(): global TESTPATH global logger diff --git a/test/case/cli/cli-output/show-interfaces.txt b/test/case/cli/cli-output/show-interfaces.txt index 1d12ab829..8d6e32828 100644 --- a/test/case/cli/cli-output/show-interfaces.txt +++ b/test/case/cli/cli-output/show-interfaces.txt @@ -6,5 +6,11 @@ br0 bridge  vlan:40u,50t br1 bridge   │ ethernet UP 02:00:00:00:00:02 └ e2 bridge FORWARDING vlan:30u pvid:30 +e2 container system  e3 ethernet UP 02:00:00:00:00:03 e4 ethernet DOWN 02:00:00:00:00:04 +veth0b container system  +veth0j ethernet UP b2:82:e3:ce:d5:9e + veth peer:veth0k + ipv4 192.168.1.1/24 (static) +veth0k container system2  diff --git a/test/case/cli/system-output/ip-addr-show.json b/test/case/cli/system-output/ip-addr-show.json index 04ad3de78..8b17f3199 100644 --- a/test/case/cli/system-output/ip-addr-show.json +++ b/test/case/cli/system-output/ip-addr-show.json @@ -625,5 +625,37 @@ "collisions": 0 } } + }, + { + "ifindex": 9, + "link_index": 8, + "ifname": "veth0j", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "noqueue", + "operstate": "UP", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "b2:82:e3:ce:d5:9e", + "broadcast": "ff:ff:ff:ff:ff:ff", + "link_netnsid": 1, + "addr_info": [ + { + "family": "inet", + "local": "192.168.1.1", + "prefixlen": 24, + "scope": "global", + "protocol": "static", + "label": "veth0j", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + } + ] } ] diff --git a/test/case/cli/system-output/ip-link-show.json b/test/case/cli/system-output/ip-link-show.json index 3d7b2dee3..3d477884a 100644 --- a/test/case/cli/system-output/ip-link-show.json +++ b/test/case/cli/system-output/ip-link-show.json @@ -618,5 +618,61 @@ "collisions": 0 } } + }, + { + "ifindex": 9, + "link_index": 8, + "ifname": "veth0j", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "noqueue", + "operstate": "UP", + "linkmode": "DEFAULT", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "b2:82:e3:ce:d5:9e", + "broadcast": "ff:ff:ff:ff:ff:ff", + "link_netnsid": 1, + "promiscuity": 0, + "allmulti": 0, + "min_mtu": 68, + "max_mtu": 65535, + "linkinfo": { + "info_kind": "veth" + }, + "inet6_addr_gen_mode": "none", + "num_tx_queues": 1, + "num_rx_queues": 1, + "gso_max_size": 65536, + "gso_max_segs": 65535, + "tso_max_size": 524280, + "tso_max_segs": 65535, + "gro_max_size": 65536, + "gso_ipv4_max_size": 65536, + "gro_ipv4_max_size": 65536, + "stats64": { + "rx": { + "bytes": 1006, + "packets": 13, + "errors": 0, + "dropped": 0, + "over_errors": 0, + "multicast": 0 + }, + "tx": { + "bytes": 18668, + "packets": 50, + "errors": 0, + "dropped": 0, + "carrier_errors": 0, + "collisions": 0 + } + } } ] diff --git a/test/case/cli/system-output/netns-57ff63cb-ip-addr-show.json b/test/case/cli/system-output/netns-57ff63cb-ip-addr-show.json new file mode 100644 index 000000000..a87540e89 --- /dev/null +++ b/test/case/cli/system-output/netns-57ff63cb-ip-addr-show.json @@ -0,0 +1,119 @@ +[ + { + "ifindex": 1, + "ifname": "lo", + "flags": [ + "LOOPBACK", + "UP", + "LOWER_UP" + ], + "mtu": 65536, + "qdisc": "noqueue", + "operstate": "UNKNOWN", + "group": "default", + "txqlen": 1000, + "link_type": "loopback", + "address": "00:00:00:00:00:00", + "broadcast": "00:00:00:00:00:00", + "addr_info": [ + { + "family": "inet", + "local": "127.0.0.1", + "prefixlen": 8, + "scope": "host", + "label": "lo", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + }, + { + "family": "inet6", + "local": "::1", + "prefixlen": 128, + "scope": "host", + "protocol": "kernel_lo", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + } + ] + }, + { + "ifindex": 3, + "ifname": "eth0", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "pfifo_fast", + "operstate": "UP", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "02:00:00:00:00:02", + "broadcast": "ff:ff:ff:ff:ff:ff", + "addr_info": [ + { + "family": "inet", + "local": "172.0.0.1", + "prefixlen": 24, + "broadcast": "172.0.0.255", + "scope": "global", + "label": "eth0", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + }, + { + "family": "inet6", + "local": "fe80::ff:fe00:2", + "prefixlen": 64, + "scope": "link", + "protocol": "kernel_ll", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + } + ] + }, + { + "ifindex": 6, + "link_index": 7, + "ifname": "eth1", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "noqueue", + "operstate": "UP", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "62:64:85:4c:7c:87", + "broadcast": "ff:ff:ff:ff:ff:ff", + "link_netnsid": 0, + "addr_info": [ + { + "family": "inet", + "local": "192.168.0.2", + "prefixlen": 24, + "broadcast": "192.168.0.255", + "scope": "global", + "label": "eth1", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + }, + { + "family": "inet6", + "local": "fe80::6064:85ff:fe4c:7c87", + "prefixlen": 64, + "scope": "link", + "protocol": "kernel_ll", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + } + ] + } +] diff --git a/test/case/cli/system-output/netns-57ff63cb-ip-link-show.json b/test/case/cli/system-output/netns-57ff63cb-ip-link-show.json new file mode 100644 index 000000000..4c852ae2f --- /dev/null +++ b/test/case/cli/system-output/netns-57ff63cb-ip-link-show.json @@ -0,0 +1,163 @@ +[ + { + "ifindex": 1, + "ifname": "lo", + "flags": [ + "LOOPBACK", + "UP", + "LOWER_UP" + ], + "mtu": 65536, + "qdisc": "noqueue", + "operstate": "UNKNOWN", + "linkmode": "DEFAULT", + "group": "default", + "txqlen": 1000, + "link_type": "loopback", + "address": "00:00:00:00:00:00", + "broadcast": "00:00:00:00:00:00", + "promiscuity": 0, + "allmulti": 0, + "min_mtu": 0, + "max_mtu": 0, + "inet6_addr_gen_mode": "eui64", + "num_tx_queues": 1, + "num_rx_queues": 1, + "gso_max_size": 65536, + "gso_max_segs": 65535, + "tso_max_size": 524280, + "tso_max_segs": 65535, + "gro_max_size": 65536, + "gso_ipv4_max_size": 65536, + "gro_ipv4_max_size": 65536, + "stats64": { + "rx": { + "bytes": 0, + "packets": 0, + "errors": 0, + "dropped": 0, + "over_errors": 0, + "multicast": 0 + }, + "tx": { + "bytes": 0, + "packets": 0, + "errors": 0, + "dropped": 0, + "carrier_errors": 0, + "collisions": 0 + } + } + }, + { + "ifindex": 3, + "ifname": "eth0", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "pfifo_fast", + "operstate": "UP", + "linkmode": "DEFAULT", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "02:00:00:00:00:02", + "broadcast": "ff:ff:ff:ff:ff:ff", + "promiscuity": 0, + "allmulti": 0, + "min_mtu": 68, + "max_mtu": 65535, + "inet6_addr_gen_mode": "eui64", + "num_tx_queues": 1, + "num_rx_queues": 1, + "gso_max_size": 65536, + "gso_max_segs": 65535, + "tso_max_size": 65536, + "tso_max_segs": 65535, + "gro_max_size": 65536, + "gso_ipv4_max_size": 65536, + "gro_ipv4_max_size": 65536, + "parentbus": "virtio", + "parentdev": "virtio3", + "ifalias": "e2", + "stats64": { + "rx": { + "bytes": 0, + "packets": 0, + "errors": 0, + "dropped": 0, + "over_errors": 0, + "multicast": 0 + }, + "tx": { + "bytes": 1006, + "packets": 13, + "errors": 0, + "dropped": 0, + "carrier_errors": 0, + "collisions": 0 + } + } + }, + { + "ifindex": 6, + "link_index": 7, + "ifname": "eth1", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "noqueue", + "operstate": "UP", + "linkmode": "DEFAULT", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "62:64:85:4c:7c:87", + "broadcast": "ff:ff:ff:ff:ff:ff", + "link_netnsid": 0, + "promiscuity": 0, + "allmulti": 0, + "min_mtu": 68, + "max_mtu": 65535, + "linkinfo": { + "info_kind": "veth" + }, + "inet6_addr_gen_mode": "eui64", + "num_tx_queues": 1, + "num_rx_queues": 1, + "gso_max_size": 65536, + "gso_max_segs": 65535, + "tso_max_size": 524280, + "tso_max_segs": 65535, + "gro_max_size": 65536, + "gso_ipv4_max_size": 65536, + "gro_ipv4_max_size": 65536, + "ifalias": "veth0b", + "stats64": { + "rx": { + "bytes": 17643, + "packets": 44, + "errors": 0, + "dropped": 24, + "over_errors": 0, + "multicast": 0 + }, + "tx": { + "bytes": 1006, + "packets": 13, + "errors": 0, + "dropped": 0, + "carrier_errors": 0, + "collisions": 0 + } + } + } +] diff --git a/test/case/cli/system-output/netns-db5ad90e-ip-addr-show.json b/test/case/cli/system-output/netns-db5ad90e-ip-addr-show.json new file mode 100644 index 000000000..28a207bb5 --- /dev/null +++ b/test/case/cli/system-output/netns-db5ad90e-ip-addr-show.json @@ -0,0 +1,80 @@ +[ + { + "ifindex": 1, + "ifname": "lo", + "flags": [ + "LOOPBACK", + "UP", + "LOWER_UP" + ], + "mtu": 65536, + "qdisc": "noqueue", + "operstate": "UNKNOWN", + "group": "default", + "txqlen": 1000, + "link_type": "loopback", + "address": "00:00:00:00:00:00", + "broadcast": "00:00:00:00:00:00", + "addr_info": [ + { + "family": "inet", + "local": "127.0.0.1", + "prefixlen": 8, + "scope": "host", + "label": "lo", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + }, + { + "family": "inet6", + "local": "::1", + "prefixlen": 128, + "scope": "host", + "protocol": "kernel_lo", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + } + ] + }, + { + "ifindex": 8, + "link_index": 9, + "ifname": "eth0", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "noqueue", + "operstate": "UP", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "c2:1b:78:88:e2:b8", + "broadcast": "ff:ff:ff:ff:ff:ff", + "link_netnsid": 0, + "addr_info": [ + { + "family": "inet", + "local": "192.168.1.2", + "prefixlen": 24, + "broadcast": "192.168.1.255", + "scope": "global", + "label": "eth0", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + }, + { + "family": "inet6", + "local": "fe80::c01b:78ff:fe88:e2b8", + "prefixlen": 64, + "scope": "link", + "protocol": "kernel_ll", + "valid_life_time": 4294967295, + "preferred_life_time": 4294967295 + } + ] + } +] diff --git a/test/case/cli/system-output/netns-db5ad90e-ip-link-show.json b/test/case/cli/system-output/netns-db5ad90e-ip-link-show.json new file mode 100644 index 000000000..dd2d8006c --- /dev/null +++ b/test/case/cli/system-output/netns-db5ad90e-ip-link-show.json @@ -0,0 +1,109 @@ +[ + { + "ifindex": 1, + "ifname": "lo", + "flags": [ + "LOOPBACK", + "UP", + "LOWER_UP" + ], + "mtu": 65536, + "qdisc": "noqueue", + "operstate": "UNKNOWN", + "linkmode": "DEFAULT", + "group": "default", + "txqlen": 1000, + "link_type": "loopback", + "address": "00:00:00:00:00:00", + "broadcast": "00:00:00:00:00:00", + "promiscuity": 0, + "allmulti": 0, + "min_mtu": 0, + "max_mtu": 0, + "inet6_addr_gen_mode": "eui64", + "num_tx_queues": 1, + "num_rx_queues": 1, + "gso_max_size": 65536, + "gso_max_segs": 65535, + "tso_max_size": 524280, + "tso_max_segs": 65535, + "gro_max_size": 65536, + "gso_ipv4_max_size": 65536, + "gro_ipv4_max_size": 65536, + "stats64": { + "rx": { + "bytes": 0, + "packets": 0, + "errors": 0, + "dropped": 0, + "over_errors": 0, + "multicast": 0 + }, + "tx": { + "bytes": 0, + "packets": 0, + "errors": 0, + "dropped": 0, + "carrier_errors": 0, + "collisions": 0 + } + } + }, + { + "ifindex": 8, + "link_index": 9, + "ifname": "eth0", + "flags": [ + "BROADCAST", + "MULTICAST", + "UP", + "LOWER_UP" + ], + "mtu": 1500, + "qdisc": "noqueue", + "operstate": "UP", + "linkmode": "DEFAULT", + "group": "default", + "txqlen": 1000, + "link_type": "ether", + "address": "c2:1b:78:88:e2:b8", + "broadcast": "ff:ff:ff:ff:ff:ff", + "link_netnsid": 0, + "promiscuity": 0, + "allmulti": 0, + "min_mtu": 68, + "max_mtu": 65535, + "linkinfo": { + "info_kind": "veth" + }, + "inet6_addr_gen_mode": "eui64", + "num_tx_queues": 1, + "num_rx_queues": 1, + "gso_max_size": 65536, + "gso_max_segs": 65535, + "tso_max_size": 524280, + "tso_max_segs": 65535, + "gro_max_size": 65536, + "gso_ipv4_max_size": 65536, + "gro_ipv4_max_size": 65536, + "ifalias": "veth0k", + "stats64": { + "rx": { + "bytes": 15197, + "packets": 37, + "errors": 0, + "dropped": 22, + "over_errors": 0, + "multicast": 0 + }, + "tx": { + "bytes": 1006, + "packets": 13, + "errors": 0, + "dropped": 0, + "carrier_errors": 0, + "collisions": 0 + } + } + } +] diff --git a/test/case/cli/system-output/netns-list.json b/test/case/cli/system-output/netns-list.json new file mode 100644 index 000000000..c8fe6406b --- /dev/null +++ b/test/case/cli/system-output/netns-list.json @@ -0,0 +1,10 @@ +[ + { + "name": "57ff63cb", + "id": 0 + }, + { + "name": "db5ad90e", + "id": 1 + } +] diff --git a/test/case/cli/system-output/podman-ps.json b/test/case/cli/system-output/podman-ps.json new file mode 100644 index 000000000..c406233c0 --- /dev/null +++ b/test/case/cli/system-output/podman-ps.json @@ -0,0 +1,73 @@ +[ + { + "AutoRemove": false, + "Command": null, + "CreatedAt": "25 minutes ago", + "Exited": false, + "ExitedAt": 1730216567, + "ExitCode": 0, + "Id": "cf054e1bc3ff7d7d6fec0cc9a0435f0c96f166e54bc9e9d92149ab53ffa60321", + "Image": "ghcr.io/kernelkit/curios:edge", + "ImageID": "cee712df3c4ea28bd3f03ca50d46e53788b1526812f4dac8d9133870eb5c49c0", + "IsInfra": false, + "Labels": { + "org.opencontainers.image.title": "curiOS", + "org.opencontainers.image.url": "https://github.com/kernelkit/curiOS" + }, + "Mounts": [], + "Names": [ + "system2" + ], + "Namespaces": { + + }, + "Networks": [ + "veth0k" + ], + "Pid": 3934, + "Pod": "", + "PodName": "", + "Ports": null, + "Size": null, + "StartedAt": 1730216629, + "State": "running", + "Status": "Up 3 minutes", + "Created": 1730215318 + }, + { + "AutoRemove": false, + "Command": null, + "CreatedAt": "22 minutes ago", + "Exited": false, + "ExitedAt": 1730216567, + "ExitCode": 0, + "Id": "400172de2290a387bd10de7c2995a0876169a4b69679b862b474c645308dcea1", + "Image": "ghcr.io/kernelkit/curios:edge", + "ImageID": "cee712df3c4ea28bd3f03ca50d46e53788b1526812f4dac8d9133870eb5c49c0", + "IsInfra": false, + "Labels": { + "org.opencontainers.image.title": "curiOS", + "org.opencontainers.image.url": "https://github.com/kernelkit/curiOS" + }, + "Mounts": [], + "Names": [ + "system" + ], + "Namespaces": { + + }, + "Networks": [ + "e2", + "veth0b" + ], + "Pid": 3933, + "Pod": "", + "PodName": "", + "Ports": null, + "Size": null, + "StartedAt": 1730216629, + "State": "running", + "Status": "Up 3 minutes", + "Created": 1730215507 + } +]