diff --git a/rule.go b/rule.go index 95f2fac..9b7b0af 100644 --- a/rule.go +++ b/rule.go @@ -28,7 +28,18 @@ type Rule struct { } func (r Rule) String() string { - return fmt.Sprintf("ip rule %d: from %s table %d", r.Priority, r.Src, r.Table) + from := "all" + if r.Src != nil && r.Src.String() != "" { + from = r.Src.String() + } + + to := "all" + if r.Dst != nil && r.Dst.String() != "" { + to = r.Dst.String() + } + + return fmt.Sprintf("ip rule %d: from %s to %s table %d", + r.Priority, from, to, r.Table) } // NewRule return empty rules. diff --git a/rule_test.go b/rule_test.go index 2458a50..0ba21db 100644 --- a/rule_test.go +++ b/rule_test.go @@ -1,3 +1,4 @@ +//go:build linux // +build linux package netlink @@ -352,6 +353,50 @@ func runRuleListFiltered(t *testing.T, family int, srcNet, dstNet *net.IPNet) { } } +func TestRuleString(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + r Rule + s string + }{ + "empty rule": { + s: "ip rule 0: from all to all table 0", + }, + "rule with src and dst equivalent to ": { + r: Rule{ + Priority: 100, + Src: &net.IPNet{IP: net.IPv4(10, 0, 0, 0)}, + Dst: &net.IPNet{IP: net.IPv4(20, 0, 0, 0)}, + Table: 99, + }, + s: "ip rule 100: from all to all table 99", + }, + "rule with src and dst": { + r: Rule{ + Priority: 100, + Src: &net.IPNet{IP: net.IPv4(10, 0, 0, 0), Mask: net.IPv4Mask(255, 255, 255, 0)}, + Dst: &net.IPNet{IP: net.IPv4(20, 0, 0, 0), Mask: net.IPv4Mask(255, 255, 255, 0)}, + Table: 99, + }, + s: "ip rule 100: from 10.0.0.0/24 to 20.0.0.0/24 table 99", + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + s := testCase.r.String() + + if s != testCase.s { + t.Errorf("expected %q but got %q", testCase.s, s) + } + }) + } +} + func ruleExists(rules []Rule, rule Rule) bool { for i := range rules { if ruleEquals(rules[i], rule) {