Skip to content

Commit

Permalink
Properly initialize AppNetworkStatus after invalid config was fixed
Browse files Browse the repository at this point in the history
When the application network configuration fails validation,
the AppNetworkStatus will be marked with an error, while the AppNum and
MACGenerator fields will remain unset. If the user corrects the invalid
part of the configuration, the handleAppNetworkModify callback will be
triggered, and validation will succeed. However, before activating
the application network, the zedrouter must ensure that AppNum and
MACGenerator are initialized. Otherwise, the zedbox will panic with
a fatal error: "undefined MAC generator."

Issue addressed by this patch was introduced in version 11.5.0

Signed-off-by: Milan Lenco <milan@zededa.com>
  • Loading branch information
milan-zededa committed Sep 19, 2024
1 parent 5b35fc2 commit 841b75b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 22 deletions.
26 changes: 26 additions & 0 deletions pkg/pillar/cmd/zedrouter/appnetwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,3 +410,29 @@ func (z *zedrouter) doAppNetworkModifyAppIntfNum(appID uuid.UUID,
}
return nil
}

// For app already deployed (before node reboot), keep using the same MAC address
// generator. Changing MAC addresses could break network config inside the app.
func (z *zedrouter) selectMACGeneratorForApp(status *types.AppNetworkStatus) error {
appKey := types.UuidToNumKey{UUID: status.UUIDandVersion.UUID}
macGenerator, _, err := z.appMACGeneratorMap.Get(appKey)
if err != nil || macGenerator == types.MACGeneratorUnspecified {
// New app or an existing app but without MAC generator ID persisted.
if z.localLegacyMACAddr {
// Use older node-scoped MAC address generator.
macGenerator = types.MACGeneratorNodeScoped
} else {
// Use newer (and preferred) globally-scoped MAC address generator.
macGenerator = types.MACGeneratorGloballyScoped
}
// Remember which MAC generator is being used for this app.
err = z.appMACGeneratorMap.Assign(appKey, macGenerator, false)
if err != nil {
err = fmt.Errorf("failed to persist MAC generator ID for app %s/%s: %v",
status.UUIDandVersion.UUID, status.DisplayName, err)
return err
}
}
status.MACGenerator = macGenerator
return nil
}
47 changes: 25 additions & 22 deletions pkg/pillar/cmd/zedrouter/pubsubhandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,29 +502,12 @@ func (z *zedrouter) handleAppNetworkCreate(ctxArg interface{}, key string,
}
status.AppNum = appNum

// For app already deployed (before node reboot), keep using the same MAC address
// generator. Changing MAC addresses could break network config inside the app.
macGenerator, _, err := z.appMACGeneratorMap.Get(appNumKey)
if err != nil || macGenerator == types.MACGeneratorUnspecified {
// New app or an existing app but without MAC generator ID persisted.
if z.localLegacyMACAddr {
// Use older node-scoped MAC address generator.
macGenerator = types.MACGeneratorNodeScoped
} else {
// Use newer (and preferred) globally-scoped MAC address generator.
macGenerator = types.MACGeneratorGloballyScoped
}
// Remember which MAC generator is being used for this app.
err = z.appMACGeneratorMap.Assign(appNumKey, macGenerator, false)
if err != nil {
err = fmt.Errorf("failed to persist MAC generator ID for app %s/%s: %v",
config.UUIDandVersion.UUID, config.DisplayName, err)
z.log.Errorf("handleAppNetworkCreate(%v): %v", config.UUIDandVersion.UUID, err)
z.addAppNetworkError(&status, "handleAppNetworkCreate", err)
return
}
err = z.selectMACGeneratorForApp(&status)
if err != nil {
z.log.Errorf("handleAppNetworkCreate(%v): %v", config.UUIDandVersion.UUID, err)
z.addAppNetworkError(&status, "handleAppNetworkCreate", err)
return
}
status.MACGenerator = macGenerator
z.publishAppNetworkStatus(&status)

// Allocate application numbers on network instances.
Expand Down Expand Up @@ -585,6 +568,26 @@ func (z *zedrouter) handleAppNetworkModify(ctxArg interface{}, key string,
return
}

// Get or (less likely) allocate number to identify the application instance.
appNumKey := types.UuidToNumKey{UUID: newConfig.UUIDandVersion.UUID}
appNum, err := z.appNumAllocator.GetOrAllocate(appNumKey)
if err != nil {
err = fmt.Errorf("failed to allocate appNum for %s/%s: %v",
newConfig.UUIDandVersion.UUID, newConfig.DisplayName, err)
z.log.Errorf("handleAppNetworkModify(%v): %v", newConfig.UUIDandVersion.UUID, err)
z.addAppNetworkError(status, "handleAppNetworkModify", err)
return
}
status.AppNum = appNum

err = z.selectMACGeneratorForApp(status)
if err != nil {
z.log.Errorf("handleAppNetworkModify(%v): %v", newConfig.UUIDandVersion.UUID, err)
z.addAppNetworkError(status, "handleAppNetworkModify", err)
return
}
z.publishAppNetworkStatus(status)

// Update numbers allocated for application interfaces.
z.checkAppNetworkModifyAppIntfNums(newConfig, status)

Expand Down

0 comments on commit 841b75b

Please sign in to comment.