Skip to content

Commit

Permalink
network: refactor ipmasq management into it's own file
Browse files Browse the repository at this point in the history
  • Loading branch information
rakelkar authored and Joel Roggeman committed Nov 6, 2017
1 parent 6d0945f commit a2f9510
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 34 deletions.
23 changes: 1 addition & 22 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"strings"
"syscall"

"github.com/coreos/go-iptables/iptables"
"github.com/coreos/pkg/flagutil"
log "github.com/golang/glog"
"golang.org/x/net/context"
Expand Down Expand Up @@ -285,7 +284,7 @@ func main() {

// Set up ipMasq if needed
if opts.ipMasq {
go setupIPMasq(config, bn)
go network.SetupAndEnsureIPMasq(config.Network, bn.Lease())
}

if err := WriteSubnetFile(opts.subnetFile, config.Network, opts.ipMasq, bn); err != nil {
Expand Down Expand Up @@ -553,26 +552,6 @@ func mustRunHealthz() {
}
}

func setupIPMasq(config *subnet.Config, bn backend.Network) {
ipt, err := iptables.New()
if err != nil {
// if we can't find iptables, give up and return
log.Errorf("Failed to set up IP Masquerade. iptables was not found: %v", err)
return
}
defer func() {
network.TeardownIPMasq(ipt, config.Network, bn.Lease())
}()
for {
// Ensure that all the rules exist every 5 seconds
if err := network.EnsureIPMasq(ipt, config.Network, bn.Lease()); err != nil {
log.Errorf("Failed to ensure IP Masquerade: %v", err)
}
time.Sleep(5 * time.Second)
}

}

func ReadSubnetFromSubnetFile(path string) ip.IP4Net {
var prevSubnet ip.IP4Net
if _, err := os.Stat(path); !os.IsNotExist(err) {
Expand Down
34 changes: 29 additions & 5 deletions network/ipmasq.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (

"github.com/coreos/flannel/pkg/ip"
"github.com/coreos/flannel/subnet"
"github.com/coreos/go-iptables/iptables"
"time"
)

type IPTablesRules interface {
Expand Down Expand Up @@ -61,7 +63,29 @@ func ipMasqRulesExist(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) (bo
return true, nil
}

func EnsureIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
func SetupAndEnsureIPMasq(network ip.IP4Net, lease *subnet.Lease) {
ipt, err := iptables.New()
if err != nil {
// if we can't find iptables, give up and return
log.Errorf("Failed to setup IP Masquerade. IPTables was not found: %v", err)
return
}

defer func() {
teardownIPMasq(ipt, network, lease)
}()

for {
// Ensure that all the rules exist every 5 seconds
if err := ensureIPMasq(ipt, network, lease); err != nil {
log.Errorf("Failed to ensure IP Masquerade: %v", err)
}

time.Sleep(5 * time.Second)
}
}

func ensureIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
exists, err := ipMasqRulesExist(ipt, ipn, lease)
if err != nil {
return fmt.Errorf("Error checking rule existence: %v", err)
Expand All @@ -73,14 +97,14 @@ func EnsureIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
// Otherwise, teardown all the rules and set them up again
// We do this because the order of the rules is important
log.Info("Some iptables rules are missing; deleting and recreating rules")
TeardownIPMasq(ipt, ipn, lease)
if err = SetupIPMasq(ipt, ipn, lease); err != nil {
teardownIPMasq(ipt, ipn, lease)
if err = setupIPMasq(ipt, ipn, lease); err != nil {
return fmt.Errorf("Error setting up rules: %v", err)
}
return nil
}

func SetupIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
func setupIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
for _, rule := range rules(ipn, lease) {
log.Info("Adding iptables rule: ", strings.Join(rule, " "))
err := ipt.AppendUnique("nat", "POSTROUTING", rule...)
Expand All @@ -92,7 +116,7 @@ func SetupIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) error {
return nil
}

func TeardownIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) {
func teardownIPMasq(ipt IPTablesRules, ipn ip.IP4Net, lease *subnet.Lease) {
for _, rule := range rules(ipn, lease) {
log.Info("Deleting iptables rule: ", strings.Join(rule, " "))
// We ignore errors here because if there's an error it's almost certainly because the rule
Expand Down
14 changes: 7 additions & 7 deletions network/ipmasq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ func (mock *MockIPTables) AppendUnique(table string, chain string, rulespec ...s

func TestDeleteRules(t *testing.T) {
ipt := &MockIPTables{}
SetupIPMasq(ipt, ip.IP4Net{}, lease())
setupIPMasq(ipt, ip.IP4Net{}, lease())
if len(ipt.rules) != 4 {
t.Errorf("Should be 4 rules, there are actually %d: %#v", len(ipt.rules), ipt.rules)
}
TeardownIPMasq(ipt, ip.IP4Net{}, lease())
teardownIPMasq(ipt, ip.IP4Net{}, lease())
if len(ipt.rules) != 0 {
t.Errorf("Should be 0 rules, there are actually %d: %#v", len(ipt.rules), ipt.rules)
}
Expand All @@ -87,13 +87,13 @@ func TestDeleteRules(t *testing.T) {
func TestEnsureRules(t *testing.T) {
// If any rules are missing, they should be all deleted and recreated in the correct order
ipt_correct := &MockIPTables{}
SetupIPMasq(ipt_correct, ip.IP4Net{}, lease())
// setup a mock instance where we delete some rules and run `EnsureIPMasq`
setupIPMasq(ipt_correct, ip.IP4Net{}, lease())
// setup a mock instance where we delete some rules and run `ensureIPMasq`
ipt_recreate := &MockIPTables{}
SetupIPMasq(ipt_recreate, ip.IP4Net{}, lease())
setupIPMasq(ipt_recreate, ip.IP4Net{}, lease())
ipt_recreate.rules = ipt_recreate.rules[0:2]
EnsureIPMasq(ipt_recreate, ip.IP4Net{}, lease())
ensureIPMasq(ipt_recreate, ip.IP4Net{}, lease())
if !reflect.DeepEqual(ipt_recreate.rules, ipt_correct.rules) {
t.Errorf("iptables rules after EnsureIPMasq are incorrected. Expected: %#v, Actual: %#v", ipt_recreate.rules, ipt_correct.rules)
t.Errorf("iptables rules after ensureIPMasq are incorrected. Expected: %#v, Actual: %#v", ipt_recreate.rules, ipt_correct.rules)
}
}

0 comments on commit a2f9510

Please sign in to comment.