From b1597f7f09c70207683ce396d95cbb0b70dbeb53 Mon Sep 17 00:00:00 2001 From: Milan Lenco Date: Mon, 12 Aug 2024 11:05:46 +0200 Subject: [PATCH] Make table index part of the IP-rule definition. When wwan modem is reset by ModemManager (because it is not responsive), the wwan interface is recreated and will get a different interface index. This means that the target routing table index for the port (calculated as 500 + interface index) will change. However, if the IP address assigned by the network is the same after the reset (common in private LTE networks), then only the table index needs to be updated in the corresponding IP rule. But this will be missed because table index is not part of the IP rule definition (SrcIPRule struct) and instead it is calculated on-demand inside the Create/Modify method of the configurator. As a result, there is no change detected by the SrcIPRule.Equal() method between the current and the new intended state, hence Modify method is not called by the reconciler and IP rule is not updated after modem reset. In this commit this is fixed by adding the table ID into the IP rule definition. In theory, this can also affect wlan or eth interface if there is e.g. a driver reset and the interface is recreated (while getting the same IP). However, with cellular modems this is more likely because they are quite flaky and ModemManager resets them when they get stuck. Signed-off-by: Milan Lenco (cherry picked from commit 695652be42a7f38ae6eabdde3d2860cdec10ec3f) --- pkg/pillar/dpcreconciler/linux.go | 1 + .../dpcreconciler/linuxitems/srciprule.go | 23 ++++--------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/pkg/pillar/dpcreconciler/linux.go b/pkg/pillar/dpcreconciler/linux.go index d3f3f11ea4..f29dd04f68 100644 --- a/pkg/pillar/dpcreconciler/linux.go +++ b/pkg/pillar/dpcreconciler/linux.go @@ -1049,6 +1049,7 @@ func (r *LinuxDpcReconciler) getIntendedSrcIPRules(dpc types.DevicePortConfig) d AdapterIfName: port.IfName, IPAddr: ipAddr.IP, Priority: devicenetwork.PbrLocalOrigPrio, + Table: devicenetwork.DPCBaseRTIndex + ifIndex, }, nil) } } diff --git a/pkg/pillar/dpcreconciler/linuxitems/srciprule.go b/pkg/pillar/dpcreconciler/linuxitems/srciprule.go index aed0db3cc2..b2c62465dd 100644 --- a/pkg/pillar/dpcreconciler/linuxitems/srciprule.go +++ b/pkg/pillar/dpcreconciler/linuxitems/srciprule.go @@ -11,7 +11,6 @@ import ( "github.com/lf-edge/eve-libs/depgraph" "github.com/lf-edge/eve/pkg/pillar/base" - "github.com/lf-edge/eve/pkg/pillar/devicenetwork" "github.com/lf-edge/eve/pkg/pillar/dpcreconciler/genericitems" "github.com/lf-edge/eve/pkg/pillar/netmonitor" "github.com/lf-edge/eve/pkg/pillar/utils/netutils" @@ -25,6 +24,7 @@ type SrcIPRule struct { AdapterIfName string IPAddr net.IP Priority int + Table int } // Name combines interface name with the IP address to construct @@ -46,7 +46,7 @@ func (r SrcIPRule) Type() string { // Equal is a comparison method for two equally-named src-IP-rule instances. func (r SrcIPRule) Equal(other depgraph.Item) bool { r2 := other.(SrcIPRule) - return r.Priority == r2.Priority + return r.Priority == r2.Priority && r.Table == r2.Table } // External returns false. @@ -57,8 +57,8 @@ func (r SrcIPRule) External() bool { // String describes source-based IP rule. func (r SrcIPRule) String() string { return fmt.Sprintf("Source-based IP rule: "+ - "{adapter: %s, ifName: %s, ip: %s, prio: %d}", - r.AdapterLL, r.AdapterIfName, r.IPAddr, r.Priority) + "{adapter: %s, ifName: %s, ip: %s, prio: %d, table: %d}", + r.AdapterLL, r.AdapterIfName, r.IPAddr, r.Priority, r.Table) } // Dependencies lists the referenced adapter as the only dependency. @@ -94,20 +94,7 @@ func (c *SrcIPRuleConfigurator) Create(ctx context.Context, item depgraph.Item) func (c *SrcIPRuleConfigurator) makeNetlinkRule(rule SrcIPRule) (*netlink.Rule, error) { r := netlink.NewRule() - ifIdx, exists, err := c.NetworkMonitor.GetInterfaceIndex(rule.AdapterIfName) - if !exists { - // Dependencies should prevent this. - err := fmt.Errorf("missing interface %s", rule.AdapterIfName) - c.Log.Error() - return nil, err - } - if err != nil { - err := fmt.Errorf("GetInterfaceIndex(%s) failed: %v", - rule.AdapterIfName, err) - c.Log.Error() - return nil, err - } - r.Table = devicenetwork.DPCBaseRTIndex + ifIdx + r.Table = rule.Table r.Priority = rule.Priority r.Family = netutils.HostFamily(rule.IPAddr) r.Src = netutils.HostSubnet(rule.IPAddr)