Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Kenneth Endfinger
lexhuismans
Ettore Simone
luoling8192
xraystyle
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ Goal of this utility is to provide compatible CLI with [iproute2], supporting sa
* `ip neigh help`
* `bridge help`
* `bridge link help`
* `ss help`
* `ss help`
* Options
* Brief output mode: `ip -br link` or `ip -br addr`
* Link module (Interfaces)
* List local interfaces `ip link`
* List interfaces in brief format `ip -br link`
* Show one interface `ip link show en0`
* Shutdown interface `ip link set dev en0 down`
* Start interface `ip link set dev en0 up`
Expand All @@ -78,6 +81,7 @@ Goal of this utility is to provide compatible CLI with [iproute2], supporting sa
* IPv6 (NDP) neighbours are being flushed for all interfaces
* Address module
* List all addresses `ip addr`
* List all addresses in brief format `ip -br addr`
* List IPv4 addresses `ip -4 addr`
* List IPv6 addresses `ip -6 addr`
* Add address to interface `ip addr add 10.0.0.5/24 dev en0`
Expand Down Expand Up @@ -119,6 +123,13 @@ Goal of this utility is to provide compatible CLI with [iproute2], supporting sa
* Same options work for `bridge` and `ss` commands

## Changelog
<details open>
<summary><b>HEAD</b></summary>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge it with the HEAD section below.


- Added `--brief` option for show commands (https://github.com/brona/iproute2mac/issues/42, PR https://github.com/brona/iproute2mac/pull/69)

</details>

<details open>
<summary><b>HEAD</b></summary>

Expand Down
93 changes: 62 additions & 31 deletions src/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def parse_ifconfig(res, af, address):
return links


def link_addr_show(argv, af, json_print, pretty_json, color, address):
def link_addr_show(argv, af, json_print, pretty_json, color, address, brief):
if len(argv) > 0 and argv[0] == "dev":
argv.pop(0)
if len(argv) > 0:
Expand All @@ -114,35 +114,62 @@ def link_addr_show(argv, af, json_print, pretty_json, color, address):
return json_dump(links, pretty_json)

for l in links:
print("%d: %s: <%s> mtu %d status %s" % (
l["ifindex"],
colorize_ifname(color, l["ifname"]),
",".join(l["flags"]),
l["mtu"],
colorize_op_state(color, l["operstate"])
))
print(
" link/" + l["link_type"] +
((" " + colorize_mac(color, l["address"])) if "address" in l else "") +
((" brd " + colorize_mac(color, l["broadcast"])) if "broadcast" in l else "")
)
for a in l.get("addr_info", []):
if brief:
# Brief format: interface_name STATUS ip_addresses...
# Interface name (left-padded to align)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ifname_colored = colorize_ifname(color, l["ifname"])
ifname_padding = max(0, 16 - len(l["ifname"]))
line = ifname_colored + " " * ifname_padding + " "

# Status
status_colored = colorize_op_state(color, l["operstate"])
status_padding = max(0, 8 - len(l["operstate"]))
line += status_colored + " " * status_padding

# Add addresses
addrs = []
for a in l.get("addr_info", []):
addr_str = "%s/%d" % (colorize_inet(color, a["family"], a["local"]), a["prefixlen"])
addrs.append(addr_str)

# For link output, show MAC address
if not address and "address" in l:
addrs.insert(0, colorize_mac(color, l["address"]))

# Add minimum 7 spaces before first address, then single space between addresses
if addrs:
line += " " + " ".join(addrs)
print(line)
else:
print("%d: %s: <%s> mtu %d status %s" % (
l["ifindex"],
colorize_ifname(color, l["ifname"]),
",".join(l["flags"]),
l["mtu"],
colorize_op_state(color, l["operstate"])
))
print(
" %s %s" % (a["family"], colorize_inet(color, a["family"], a["local"])) +
((" peer %s" % colorize_inet(color, a["family"], a["address"])) if "address" in a else "") +
"/%d" % (a["prefixlen"]) +
((" brd " + colorize_inet(color, a["family"], a["broadcast"])) if "broadcast" in a else "")
" link/" + l["link_type"] +
((" " + colorize_mac(color, l["address"])) if "address" in l else "") +
((" brd " + colorize_mac(color, l["broadcast"])) if "broadcast" in l else "")
)
for a in l.get("addr_info", []):
print(
" %s %s" % (a["family"], colorize_inet(color, a["family"], a["local"])) +
((" peer %s" % colorize_inet(color, a["family"], a["address"])) if "address" in a else "") +
"/%d" % (a["prefixlen"]) +
((" brd " + colorize_inet(color, a["family"], a["broadcast"])) if "broadcast" in a else "")
)

return True


# Help
def do_help(argv=None, af=None, json_print=None, pretty_json=None, color=None):
def do_help(argv=None, af=None, json_print=None, pretty_json=None, color=None, brief=None):
perror("Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }")
perror("where OBJECT := { link | addr | route | neigh }")
perror(" OPTIONS := { -V[ersion] | -j[son] | -p[retty] | -c[olor] |")
perror(" -4 | -6 }")
perror(" -br[ief] | -4 | -6 }")
perror(HELP_ADDENDUM)
exit(255)

Expand Down Expand Up @@ -184,7 +211,7 @@ def do_help_neigh():

# Route Module
@help_msg(do_help_route)
def do_route(argv, af, json_print, pretty_json, color):
def do_route(argv, af, json_print, pretty_json, color, brief):
if not argv or (
any_startswith(["show", "lst", "list"], argv[0]) and len(argv) == 1
):
Expand Down Expand Up @@ -409,13 +436,13 @@ def do_route_get(argv, af, json_print, pretty_json, color):

# Addr Module
@help_msg(do_help_addr)
def do_addr(argv, af, json_print, pretty_json, color):
def do_addr(argv, af, json_print, pretty_json, color, brief):
if not argv:
argv.append("show")

if any_startswith(["show", "lst", "list"], argv[0]):
argv.pop(0)
return do_addr_show(argv, af, json_print, pretty_json, color)
return do_addr_show(argv, af, json_print, pretty_json, color, brief)
elif "add".startswith(argv[0]) and len(argv) >= 3:
argv.pop(0)
return do_addr_add(argv, af)
Expand All @@ -427,8 +454,8 @@ def do_addr(argv, af, json_print, pretty_json, color):
return True


def do_addr_show(argv, af, json_print, pretty_json, color):
return link_addr_show(argv, af, json_print, pretty_json, color, True)
def do_addr_show(argv, af, json_print, pretty_json, color, brief):
return link_addr_show(argv, af, json_print, pretty_json, color, True, brief)


def do_addr_add(argv, af):
Expand Down Expand Up @@ -481,13 +508,13 @@ def do_addr_del(argv, af):

# Link module
@help_msg(do_help_link)
def do_link(argv, af, json_print, pretty_json, color):
def do_link(argv, af, json_print, pretty_json, color, brief):
if not argv:
argv.append("show")

if any_startswith(["show", "lst", "list"], argv[0]):
argv.pop(0)
return do_link_show(argv, af, json_print, pretty_json, color)
return do_link_show(argv, af, json_print, pretty_json, color, brief)
elif "set".startswith(argv[0]):
argv.pop(0)
return do_link_set(argv, af)
Expand All @@ -496,8 +523,8 @@ def do_link(argv, af, json_print, pretty_json, color):
return True


def do_link_show(argv, af, json_print, pretty_json, color):
return link_addr_show(argv, af, json_print, pretty_json, color, False)
def do_link_show(argv, af, json_print, pretty_json, color, brief):
return link_addr_show(argv, af, json_print, pretty_json, color, False, brief)


def do_link_set(argv, af):
Expand Down Expand Up @@ -550,7 +577,7 @@ def do_link_set(argv, af):

# Neigh module
@help_msg(do_help_neigh)
def do_neigh(argv, af, json_print, pretty_json, color):
def do_neigh(argv, af, json_print, pretty_json, color, brief):
if not argv:
argv.append("show")

Expand Down Expand Up @@ -694,6 +721,7 @@ def main(argv):
af = -1 # default / both
json_print = False
pretty_json = False
brief = False
color_mode = "never"

while argv and argv[0].startswith("-"):
Expand All @@ -706,6 +734,9 @@ def main(argv):
elif argv[0] == "-4":
af = 4
argv.pop(0)
elif "-brief".startswith(argv[0]):
brief = True
argv.pop(0)
elif "-color".startswith(argv[0].split("=")[0]):
# 'always' is default if -color is set without any value
color_mode = argv[0].split("=")[1] if "=" in argv[0] else "always"
Expand Down Expand Up @@ -738,7 +769,7 @@ def main(argv):
argv.pop(0)
# Functions return true or terminate with exit(255)
# See help_msg and do_help*
return cmd_func(argv, af, json_print, pretty_json, color_scheme)
return cmd_func(argv, af, json_print, pretty_json, color_scheme, brief)

perror('Object "{}" is unknown, try "ip help".'.format(argv[0]))
exit(1)
Expand Down
40 changes: 40 additions & 0 deletions test/commands.sh
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,32 @@ $ip_cmd a s

! $ip_cmd addr asdf

## brief format tests

# Test basic -br addr show
$ip_cmd -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +"

# Test -br a shorthand
$ip_cmd -br a | grep -E "^lo[0-9]* +[A-Z]+ +"

# Test -br with specific device
$ip_cmd -br addr show dev lo0 | grep -E "^lo0 +[A-Z]+ +"

# Test -br with -4 (IPv4 only)
$ip_cmd -4 -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +" | grep "127.0.0.1"

# Test -br with -6 (IPv6 only)
$ip_cmd -6 -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +" | grep "::1"

# Test -br with -j (JSON output should override brief)
$ip_cmd -br -j addr show | perl -MJSON -e 'decode_json(<STDIN>)'

# Test order: -br before command
$ip_cmd -br addr show | grep -E "^lo[0-9]* +[A-Z]+ +"

# Test order: -br after command (should also work)
$ip_cmd addr -br show | grep -E "^lo[0-9]* +[A-Z]+ +"


# link

Expand All @@ -169,6 +195,20 @@ $ip_cmd l s | grep mtu

! $ip_cmd link asdf

## link brief format tests

# Test basic -br link show
$ip_cmd -br link show | grep -E "^lo[0-9]* +[A-Z]+ +"

# Test -br l shorthand
$ip_cmd -br l | grep -E "^lo[0-9]* +[A-Z]+ +"

# Test -br with specific device
$ip_cmd -br link show lo0 | grep -E "^lo0 +[A-Z]+ +"

# Test -br with -j (JSON output should override brief)
$ip_cmd -br -j link show | perl -MJSON -e 'decode_json(<STDIN>)'

# neigh

$ip_cmd nei help 2>&1 >/dev/null | grep "Usage: ip neighbour"
Expand Down