Skip to content

Commit

Permalink
datapath/linux: make sure we have a local rule with proto kernel
Browse files Browse the repository at this point in the history
This reverts commit 9d60341.

Signed-off-by: Nikolay Aleksandrov <nikolay@isovalent.com>
  • Loading branch information
Nikolay Aleksandrov authored and aanm committed May 23, 2023
1 parent 3afe3b1 commit a63aabc
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
6 changes: 6 additions & 0 deletions daemon/cmd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"golang.org/x/sync/semaphore"
"golang.org/x/sys/unix"

"github.com/cilium/cilium/api/v1/models"
health "github.com/cilium/cilium/cilium-health/launch"
Expand Down Expand Up @@ -282,6 +283,11 @@ func (d *Daemon) init() error {
return fmt.Errorf("failed while reinitializing datapath: %w", err)
}

if err := linuxdatapath.NodeEnsureLocalIPRule(); errors.Is(err, unix.EEXIST) {
log.WithError(err).Warn("Failed to ensure local IP rules")
} else if err != nil {
return fmt.Errorf("failed to ensure local IP rules: %w", err)
}
}

return nil
Expand Down
87 changes: 87 additions & 0 deletions pkg/datapath/linux/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1897,3 +1897,90 @@ func NodeDeviceNameWithDefaultRoute() (string, error) {
}
return link.Attrs().Name, nil
}

func deleteOldLocalRule(family int, rule route.Rule) error {
var familyStr string

// sanity check, nothing to do if the rule is the same
if linux_defaults.RTProto == unix.RTPROT_UNSPEC {
return nil
}

if family == netlink.FAMILY_V4 {
familyStr = "IPv4"
} else {
familyStr = "IPv6"
}

localRules, err := route.ListRules(family, &rule)
if err != nil {
return fmt.Errorf("could not list local %s rules: %w", familyStr, err)
}

// we need to check for the old rule and make sure it's before the new one
oldPos := -1
found := false
for pos, rule := range localRules {
// mark the first unspec rule that matches
if oldPos == -1 && rule.Protocol == unix.RTPROT_UNSPEC {
oldPos = pos
}

if rule.Protocol == linux_defaults.RTProto {
// mark it as found only if it's before the new one
if oldPos != -1 {
found = true
}
break
}
}

if found == true {
err := route.DeleteRule(family, rule)
if err != nil {
return fmt.Errorf("could not delete old %s local rule: %w", familyStr, err)
}
log.WithFields(logrus.Fields{"family": familyStr}).Info("Deleting old local lookup rule")
}

return nil
}

// NodeEnsureLocalIPRule checks if Cilium local lookup rule (usually 100)
// was installed and has proper protocol
func NodeEnsureLocalIPRule() error {
// we have the Cilium local lookup rule only if the proxy rule is present
if !option.Config.InstallIptRules || !option.Config.EnableL7Proxy {
return nil
}

localRule := route.Rule{Priority: linux_defaults.RulePriorityLocalLookup, Table: unix.RT_TABLE_LOCAL, Mark: -1, Mask: -1, Protocol: linux_defaults.RTProto}
oldRule := localRule
oldRule.Protocol = unix.RTPROT_UNSPEC

if option.Config.EnableIPv4 {
err := route.ReplaceRule(localRule)
if err != nil {
return fmt.Errorf("could not replace IPv4 local rule: %w", err)
}

err = deleteOldLocalRule(netlink.FAMILY_V4, oldRule)
if err != nil {
return err
}
}

if option.Config.EnableIPv6 {
err := route.ReplaceRuleIPv6(localRule)
if err != nil {
return fmt.Errorf("could not replace IPv6 local rule: %w", err)
}

err = deleteOldLocalRule(netlink.FAMILY_V6, oldRule)
if err != nil {
return err
}
}

return nil
}

0 comments on commit a63aabc

Please sign in to comment.