Maint: internal/routing IP rules functions
- Take in `src` as `*net.IPNet` instead of `net.IP` - Take `dst` IP network - Debug logged `ip rule` dynamically built - Add unit tests for all IP rules functions
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package netlink
|
||||
|
||||
//go:generate mockgen -destination=mock_$GOPACKAGE/$GOFILE . NetLinker
|
||||
|
||||
var _ NetLinker = (*NetLink)(nil)
|
||||
|
||||
type NetLinker interface {
|
||||
|
||||
251
internal/netlink/mock_netlink/interface.go
Normal file
251
internal/netlink/mock_netlink/interface.go
Normal file
@@ -0,0 +1,251 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/qdm12/gluetun/internal/netlink (interfaces: NetLinker)
|
||||
|
||||
// Package mock_netlink is a generated GoMock package.
|
||||
package mock_netlink
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
netlink "github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
// MockNetLinker is a mock of NetLinker interface.
|
||||
type MockNetLinker struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockNetLinkerMockRecorder
|
||||
}
|
||||
|
||||
// MockNetLinkerMockRecorder is the mock recorder for MockNetLinker.
|
||||
type MockNetLinkerMockRecorder struct {
|
||||
mock *MockNetLinker
|
||||
}
|
||||
|
||||
// NewMockNetLinker creates a new mock instance.
|
||||
func NewMockNetLinker(ctrl *gomock.Controller) *MockNetLinker {
|
||||
mock := &MockNetLinker{ctrl: ctrl}
|
||||
mock.recorder = &MockNetLinkerMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockNetLinker) EXPECT() *MockNetLinkerMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// AddrAdd mocks base method.
|
||||
func (m *MockNetLinker) AddrAdd(arg0 netlink.Link, arg1 *netlink.Addr) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddrAdd", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AddrAdd indicates an expected call of AddrAdd.
|
||||
func (mr *MockNetLinkerMockRecorder) AddrAdd(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrAdd", reflect.TypeOf((*MockNetLinker)(nil).AddrAdd), arg0, arg1)
|
||||
}
|
||||
|
||||
// AddrList mocks base method.
|
||||
func (m *MockNetLinker) AddrList(arg0 netlink.Link, arg1 int) ([]netlink.Addr, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddrList", arg0, arg1)
|
||||
ret0, _ := ret[0].([]netlink.Addr)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AddrList indicates an expected call of AddrList.
|
||||
func (mr *MockNetLinkerMockRecorder) AddrList(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrList", reflect.TypeOf((*MockNetLinker)(nil).AddrList), arg0, arg1)
|
||||
}
|
||||
|
||||
// LinkAdd mocks base method.
|
||||
func (m *MockNetLinker) LinkAdd(arg0 netlink.Link) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LinkAdd", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LinkAdd indicates an expected call of LinkAdd.
|
||||
func (mr *MockNetLinkerMockRecorder) LinkAdd(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkAdd", reflect.TypeOf((*MockNetLinker)(nil).LinkAdd), arg0)
|
||||
}
|
||||
|
||||
// LinkByIndex mocks base method.
|
||||
func (m *MockNetLinker) LinkByIndex(arg0 int) (netlink.Link, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LinkByIndex", arg0)
|
||||
ret0, _ := ret[0].(netlink.Link)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// LinkByIndex indicates an expected call of LinkByIndex.
|
||||
func (mr *MockNetLinkerMockRecorder) LinkByIndex(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkByIndex", reflect.TypeOf((*MockNetLinker)(nil).LinkByIndex), arg0)
|
||||
}
|
||||
|
||||
// LinkByName mocks base method.
|
||||
func (m *MockNetLinker) LinkByName(arg0 string) (netlink.Link, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LinkByName", arg0)
|
||||
ret0, _ := ret[0].(netlink.Link)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// LinkByName indicates an expected call of LinkByName.
|
||||
func (mr *MockNetLinkerMockRecorder) LinkByName(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkByName", reflect.TypeOf((*MockNetLinker)(nil).LinkByName), arg0)
|
||||
}
|
||||
|
||||
// LinkDel mocks base method.
|
||||
func (m *MockNetLinker) LinkDel(arg0 netlink.Link) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LinkDel", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LinkDel indicates an expected call of LinkDel.
|
||||
func (mr *MockNetLinkerMockRecorder) LinkDel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkDel", reflect.TypeOf((*MockNetLinker)(nil).LinkDel), arg0)
|
||||
}
|
||||
|
||||
// LinkList mocks base method.
|
||||
func (m *MockNetLinker) LinkList() ([]netlink.Link, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LinkList")
|
||||
ret0, _ := ret[0].([]netlink.Link)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// LinkList indicates an expected call of LinkList.
|
||||
func (mr *MockNetLinkerMockRecorder) LinkList() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkList", reflect.TypeOf((*MockNetLinker)(nil).LinkList))
|
||||
}
|
||||
|
||||
// LinkSetUp mocks base method.
|
||||
func (m *MockNetLinker) LinkSetUp(arg0 netlink.Link) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "LinkSetUp", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// LinkSetUp indicates an expected call of LinkSetUp.
|
||||
func (mr *MockNetLinkerMockRecorder) LinkSetUp(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkSetUp", reflect.TypeOf((*MockNetLinker)(nil).LinkSetUp), arg0)
|
||||
}
|
||||
|
||||
// RouteAdd mocks base method.
|
||||
func (m *MockNetLinker) RouteAdd(arg0 *netlink.Route) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RouteAdd", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RouteAdd indicates an expected call of RouteAdd.
|
||||
func (mr *MockNetLinkerMockRecorder) RouteAdd(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RouteAdd", reflect.TypeOf((*MockNetLinker)(nil).RouteAdd), arg0)
|
||||
}
|
||||
|
||||
// RouteDel mocks base method.
|
||||
func (m *MockNetLinker) RouteDel(arg0 *netlink.Route) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RouteDel", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RouteDel indicates an expected call of RouteDel.
|
||||
func (mr *MockNetLinkerMockRecorder) RouteDel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RouteDel", reflect.TypeOf((*MockNetLinker)(nil).RouteDel), arg0)
|
||||
}
|
||||
|
||||
// RouteList mocks base method.
|
||||
func (m *MockNetLinker) RouteList(arg0 netlink.Link, arg1 int) ([]netlink.Route, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RouteList", arg0, arg1)
|
||||
ret0, _ := ret[0].([]netlink.Route)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// RouteList indicates an expected call of RouteList.
|
||||
func (mr *MockNetLinkerMockRecorder) RouteList(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RouteList", reflect.TypeOf((*MockNetLinker)(nil).RouteList), arg0, arg1)
|
||||
}
|
||||
|
||||
// RouteReplace mocks base method.
|
||||
func (m *MockNetLinker) RouteReplace(arg0 *netlink.Route) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RouteReplace", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RouteReplace indicates an expected call of RouteReplace.
|
||||
func (mr *MockNetLinkerMockRecorder) RouteReplace(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RouteReplace", reflect.TypeOf((*MockNetLinker)(nil).RouteReplace), arg0)
|
||||
}
|
||||
|
||||
// RuleAdd mocks base method.
|
||||
func (m *MockNetLinker) RuleAdd(arg0 *netlink.Rule) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RuleAdd", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RuleAdd indicates an expected call of RuleAdd.
|
||||
func (mr *MockNetLinkerMockRecorder) RuleAdd(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RuleAdd", reflect.TypeOf((*MockNetLinker)(nil).RuleAdd), arg0)
|
||||
}
|
||||
|
||||
// RuleDel mocks base method.
|
||||
func (m *MockNetLinker) RuleDel(arg0 *netlink.Rule) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RuleDel", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RuleDel indicates an expected call of RuleDel.
|
||||
func (mr *MockNetLinkerMockRecorder) RuleDel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RuleDel", reflect.TypeOf((*MockNetLinker)(nil).RuleDel), arg0)
|
||||
}
|
||||
|
||||
// RuleList mocks base method.
|
||||
func (m *MockNetLinker) RuleList(arg0 int) ([]netlink.Rule, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RuleList", arg0)
|
||||
ret0, _ := ret[0].([]netlink.Rule)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// RuleList indicates an expected call of RuleList.
|
||||
func (mr *MockNetLinkerMockRecorder) RuleList(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RuleList", reflect.TypeOf((*MockNetLinker)(nil).RuleList), arg0)
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/netlink"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -53,8 +55,11 @@ func (r *Routing) addRuleInboundFromDefault(table int) (err error) {
|
||||
return fmt.Errorf("%w: %s", errDefaultIP, err)
|
||||
}
|
||||
|
||||
if err := r.addIPRule(defaultIP, table, inboundPriority); err != nil {
|
||||
return fmt.Errorf("%w: %s", errIPRuleAdd, err)
|
||||
defaultIPMasked32 := netlink.NewIPNet(defaultIP)
|
||||
ruleDstNet := (*net.IPNet)(nil)
|
||||
err = r.addIPRule(defaultIPMasked32, ruleDstNet, table, inboundPriority)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %s", errRuleAdd, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -66,8 +71,11 @@ func (r *Routing) delRuleInboundFromDefault(table int) (err error) {
|
||||
return fmt.Errorf("%w: %s", errDefaultIP, err)
|
||||
}
|
||||
|
||||
if err := r.deleteIPRule(defaultIP, table, inboundPriority); err != nil {
|
||||
return fmt.Errorf("%w: %s", errIPRuleAdd, err)
|
||||
defaultIPMasked32 := netlink.NewIPNet(defaultIP)
|
||||
ruleDstNet := (*net.IPNet)(nil)
|
||||
err = r.deleteIPRule(defaultIPMasked32, ruleDstNet, table, inboundPriority)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: %s", errRuleDelete, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,23 +5,21 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/netlink"
|
||||
)
|
||||
|
||||
var (
|
||||
errIPRuleAdd = errors.New("cannot add IP rule")
|
||||
errRulesList = errors.New("cannot list rules")
|
||||
)
|
||||
|
||||
func (r *Routing) addIPRule(src net.IP, table, priority int) error {
|
||||
r.logger.Debug("ip rule add from " + src.String() +
|
||||
" lookup " + strconv.Itoa(table) +
|
||||
" pref " + strconv.Itoa(priority))
|
||||
func (r *Routing) addIPRule(src, dst *net.IPNet, table, priority int) error {
|
||||
const add = true
|
||||
r.logger.Debug(ruleDbgMsg(add, src, dst, table, priority))
|
||||
|
||||
rule := netlink.NewRule()
|
||||
rule.Src = netlink.NewIPNet(src)
|
||||
rule.Src = src
|
||||
rule.Dst = dst
|
||||
rule.Priority = priority
|
||||
rule.Table = table
|
||||
|
||||
@@ -45,13 +43,13 @@ func (r *Routing) addIPRule(src net.IP, table, priority int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Routing) deleteIPRule(src net.IP, table, priority int) error {
|
||||
r.logger.Debug("ip rule del from " + src.String() +
|
||||
" lookup " + strconv.Itoa(table) +
|
||||
" pref " + strconv.Itoa(priority))
|
||||
func (r *Routing) deleteIPRule(src, dst *net.IPNet, table, priority int) error {
|
||||
const add = false
|
||||
r.logger.Debug(ruleDbgMsg(add, src, dst, table, priority))
|
||||
|
||||
rule := netlink.NewRule()
|
||||
rule.Src = netlink.NewIPNet(src)
|
||||
rule.Src = src
|
||||
rule.Dst = dst
|
||||
rule.Priority = priority
|
||||
rule.Table = table
|
||||
|
||||
@@ -72,3 +70,32 @@ func (r *Routing) deleteIPRule(src net.IP, table, priority int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ruleDbgMsg(add bool, src, dst *net.IPNet,
|
||||
table, priority int) (debugMessage string) {
|
||||
debugMessage = "ip rule"
|
||||
|
||||
if add {
|
||||
debugMessage += " add"
|
||||
} else {
|
||||
debugMessage += " del"
|
||||
}
|
||||
|
||||
if src != nil {
|
||||
debugMessage += " from " + src.String()
|
||||
}
|
||||
|
||||
if dst != nil {
|
||||
debugMessage += " to " + dst.String()
|
||||
}
|
||||
|
||||
if table != 0 {
|
||||
debugMessage += " lookup " + fmt.Sprint(table)
|
||||
}
|
||||
|
||||
if priority != -1 {
|
||||
debugMessage += " pref " + fmt.Sprint(priority)
|
||||
}
|
||||
|
||||
return debugMessage
|
||||
}
|
||||
|
||||
308
internal/routing/rules_test.go
Normal file
308
internal/routing/rules_test.go
Normal file
@@ -0,0 +1,308 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/qdm12/gluetun/internal/netlink"
|
||||
"github.com/qdm12/gluetun/internal/netlink/mock_netlink"
|
||||
"github.com/qdm12/golibs/logging/mock_logging"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func makeIPNet(t *testing.T, n byte) *net.IPNet {
|
||||
t.Helper()
|
||||
return &net.IPNet{
|
||||
IP: net.IPv4(n, n, n, 0),
|
||||
Mask: net.IPv4Mask(255, 255, 255, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func makeIPRule(t *testing.T, src, dst *net.IPNet,
|
||||
table, priority int) *netlink.Rule {
|
||||
t.Helper()
|
||||
rule := netlink.NewRule()
|
||||
rule.Src = src
|
||||
rule.Dst = dst
|
||||
rule.Table = table
|
||||
rule.Priority = priority
|
||||
return rule
|
||||
}
|
||||
|
||||
func Test_Routing_addIPRule(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
errDummy := errors.New("dummy error")
|
||||
|
||||
type ruleListCall struct {
|
||||
rules []netlink.Rule
|
||||
err error
|
||||
}
|
||||
|
||||
type ruleAddCall struct {
|
||||
expected bool
|
||||
ruleToAdd *netlink.Rule
|
||||
err error
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
src *net.IPNet
|
||||
dst *net.IPNet
|
||||
table int
|
||||
priority int
|
||||
dbgMsg string
|
||||
ruleList ruleListCall
|
||||
ruleAdd ruleAddCall
|
||||
err error
|
||||
}{
|
||||
"list error": {
|
||||
dbgMsg: "ip rule add pref 0",
|
||||
ruleList: ruleListCall{
|
||||
err: errDummy,
|
||||
},
|
||||
err: errors.New("cannot list rules: dummy error"),
|
||||
},
|
||||
"rule already exists": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 99,
|
||||
priority: 99,
|
||||
dbgMsg: "ip rule add from 1.1.1.0/24 to 2.2.2.0/24 lookup 99 pref 99",
|
||||
ruleList: ruleListCall{
|
||||
rules: []netlink.Rule{
|
||||
*makeIPRule(t, makeIPNet(t, 2), makeIPNet(t, 2), 99, 99),
|
||||
*makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
},
|
||||
},
|
||||
},
|
||||
"add rule error": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 99,
|
||||
priority: 99,
|
||||
dbgMsg: "ip rule add from 1.1.1.0/24 to 2.2.2.0/24 lookup 99 pref 99",
|
||||
ruleAdd: ruleAddCall{
|
||||
expected: true,
|
||||
ruleToAdd: makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
err: errDummy,
|
||||
},
|
||||
err: errors.New("dummy error: for rule: ip rule 99: from 1.1.1.0/24 table 99"),
|
||||
},
|
||||
"add rule success": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 99,
|
||||
priority: 99,
|
||||
dbgMsg: "ip rule add from 1.1.1.0/24 to 2.2.2.0/24 lookup 99 pref 99",
|
||||
ruleList: ruleListCall{
|
||||
rules: []netlink.Rule{
|
||||
*makeIPRule(t, makeIPNet(t, 2), makeIPNet(t, 2), 99, 99),
|
||||
*makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 101, 101),
|
||||
},
|
||||
},
|
||||
ruleAdd: ruleAddCall{
|
||||
expected: true,
|
||||
ruleToAdd: makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctrl := gomock.NewController(t)
|
||||
|
||||
logger := mock_logging.NewMockLogger(ctrl)
|
||||
logger.EXPECT().Debug(testCase.dbgMsg)
|
||||
|
||||
netLinker := mock_netlink.NewMockNetLinker(ctrl)
|
||||
netLinker.EXPECT().RuleList(netlink.FAMILY_ALL).
|
||||
Return(testCase.ruleList.rules, testCase.ruleList.err)
|
||||
if testCase.ruleAdd.expected {
|
||||
netLinker.EXPECT().RuleAdd(testCase.ruleAdd.ruleToAdd).
|
||||
Return(testCase.ruleAdd.err)
|
||||
}
|
||||
|
||||
r := Routing{
|
||||
logger: logger,
|
||||
netLinker: netLinker,
|
||||
}
|
||||
|
||||
err := r.addIPRule(testCase.src, testCase.dst,
|
||||
testCase.table, testCase.priority)
|
||||
|
||||
if testCase.err != nil {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Routing_deleteIPRule(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
errDummy := errors.New("dummy error")
|
||||
|
||||
type ruleListCall struct {
|
||||
rules []netlink.Rule
|
||||
err error
|
||||
}
|
||||
|
||||
type ruleDelCall struct {
|
||||
expected bool
|
||||
ruleToDel *netlink.Rule
|
||||
err error
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
src *net.IPNet
|
||||
dst *net.IPNet
|
||||
table int
|
||||
priority int
|
||||
dbgMsg string
|
||||
ruleList ruleListCall
|
||||
ruleDel ruleDelCall
|
||||
err error
|
||||
}{
|
||||
"list error": {
|
||||
dbgMsg: "ip rule del pref 0",
|
||||
ruleList: ruleListCall{
|
||||
err: errDummy,
|
||||
},
|
||||
err: errors.New("cannot list rules: dummy error"),
|
||||
},
|
||||
"rule delete error": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 99,
|
||||
priority: 99,
|
||||
dbgMsg: "ip rule del from 1.1.1.0/24 to 2.2.2.0/24 lookup 99 pref 99",
|
||||
ruleList: ruleListCall{
|
||||
rules: []netlink.Rule{
|
||||
*makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
},
|
||||
},
|
||||
ruleDel: ruleDelCall{
|
||||
expected: true,
|
||||
ruleToDel: makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
err: errDummy,
|
||||
},
|
||||
err: errors.New("dummy error: for rule: ip rule 99: from 1.1.1.0/24 table 99"),
|
||||
},
|
||||
"rule deleted": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 99,
|
||||
priority: 99,
|
||||
dbgMsg: "ip rule del from 1.1.1.0/24 to 2.2.2.0/24 lookup 99 pref 99",
|
||||
ruleList: ruleListCall{
|
||||
rules: []netlink.Rule{
|
||||
*makeIPRule(t, makeIPNet(t, 2), makeIPNet(t, 2), 99, 99),
|
||||
*makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
},
|
||||
},
|
||||
ruleDel: ruleDelCall{
|
||||
expected: true,
|
||||
ruleToDel: makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 99, 99),
|
||||
},
|
||||
},
|
||||
"rule does not exist": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 99,
|
||||
priority: 99,
|
||||
dbgMsg: "ip rule del from 1.1.1.0/24 to 2.2.2.0/24 lookup 99 pref 99",
|
||||
ruleList: ruleListCall{
|
||||
rules: []netlink.Rule{
|
||||
*makeIPRule(t, makeIPNet(t, 2), makeIPNet(t, 2), 99, 99),
|
||||
*makeIPRule(t, makeIPNet(t, 1), makeIPNet(t, 2), 101, 101),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctrl := gomock.NewController(t)
|
||||
|
||||
logger := mock_logging.NewMockLogger(ctrl)
|
||||
logger.EXPECT().Debug(testCase.dbgMsg)
|
||||
|
||||
netLinker := mock_netlink.NewMockNetLinker(ctrl)
|
||||
netLinker.EXPECT().RuleList(netlink.FAMILY_ALL).
|
||||
Return(testCase.ruleList.rules, testCase.ruleList.err)
|
||||
if testCase.ruleDel.expected {
|
||||
netLinker.EXPECT().RuleDel(testCase.ruleDel.ruleToDel).
|
||||
Return(testCase.ruleDel.err)
|
||||
}
|
||||
|
||||
r := Routing{
|
||||
logger: logger,
|
||||
netLinker: netLinker,
|
||||
}
|
||||
|
||||
err := r.deleteIPRule(testCase.src, testCase.dst,
|
||||
testCase.table, testCase.priority)
|
||||
|
||||
if testCase.err != nil {
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, testCase.err.Error(), err.Error())
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ruleDbgMsg(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
add bool
|
||||
src *net.IPNet
|
||||
dst *net.IPNet
|
||||
table int
|
||||
priority int
|
||||
dbgMsg string
|
||||
}{
|
||||
"default values": {
|
||||
dbgMsg: "ip rule del pref 0",
|
||||
},
|
||||
"add rule": {
|
||||
add: true,
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 100,
|
||||
priority: 101,
|
||||
dbgMsg: "ip rule add from 1.1.1.0/24 to 2.2.2.0/24 lookup 100 pref 101",
|
||||
},
|
||||
"del rule": {
|
||||
src: makeIPNet(t, 1),
|
||||
dst: makeIPNet(t, 2),
|
||||
table: 100,
|
||||
priority: 101,
|
||||
dbgMsg: "ip rule del from 1.1.1.0/24 to 2.2.2.0/24 lookup 100 pref 101",
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
testCase := testCase
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbgMsg := ruleDbgMsg(testCase.add, testCase.src,
|
||||
testCase.dst, testCase.table, testCase.priority)
|
||||
|
||||
assert.Equal(t, testCase.dbgMsg, dbgMsg)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user