Skip to content

Commit 80bbdfe

Browse files
committed
fix: Preserve kernel argument ordering
Signed-off-by: Dominik De Zordo <[email protected]>
1 parent dc8f6de commit 80bbdfe

File tree

2 files changed

+50
-18
lines changed

2 files changed

+50
-18
lines changed

kernelargs.go

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,46 +13,78 @@
1313

1414
package firecracker
1515

16-
import "strings"
16+
import (
17+
"fmt"
18+
"sort"
19+
"strings"
20+
)
1721

1822
// kernelArgs serializes+deserializes kernel boot parameters from/into a map.
1923
// Kernel docs: https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt
2024
//
2125
// "key=value" will result in map["key"] = &"value"
2226
// "key=" will result in map["key"] = &""
2327
// "key" will result in map["key"] = nil
24-
type kernelArgs map[string]*string
28+
type kernelArg struct {
29+
position uint
30+
key string
31+
value *string
32+
}
33+
34+
func (karg kernelArg) String() string {
35+
if karg.value != nil {
36+
return fmt.Sprintf("%s=%s", karg.key, *karg.value)
37+
}
38+
return karg.key
39+
}
2540

26-
// serialize the kernelArgs back to a string that can be provided
41+
type kernelArgs map[string]kernelArg
42+
43+
// serialize the sorted kernelArgs back to a string that can be provided
2744
// to the kernel
2845
func (kargs kernelArgs) String() string {
29-
var fields []string
30-
for key, value := range kargs {
31-
field := key
32-
if value != nil {
33-
field += "=" + *value
34-
}
35-
fields = append(fields, field)
46+
sortedArgs := make([]kernelArg, 0)
47+
for _, arg := range kargs {
48+
sortedArgs = append(sortedArgs, arg)
49+
}
50+
sort.SliceStable(sortedArgs, func(i, j int) bool {
51+
return sortedArgs[i].position < sortedArgs[j].position
52+
})
53+
54+
args := make([]string, 0)
55+
for _, arg := range sortedArgs {
56+
args = append(args, arg.String())
57+
}
58+
return strings.Join(args, " ")
59+
}
60+
61+
func (kargs kernelArgs) Add(key string, value *string) {
62+
kargs[key] = kernelArg{
63+
position: uint(len(kargs)),
64+
key: key,
65+
value: value,
3666
}
37-
return strings.Join(fields, " ")
3867
}
3968

4069
// deserialize the provided string to a kernelArgs map
4170
func parseKernelArgs(rawString string) kernelArgs {
42-
argMap := make(map[string]*string)
43-
for _, kv := range strings.Fields(rawString) {
71+
args := make(map[string]kernelArg)
72+
for index, kv := range strings.Fields(rawString) {
4473
// only split into up to 2 fields (before and after the first "=")
4574
kvSplit := strings.SplitN(kv, "=", 2)
4675

4776
key := kvSplit[0]
48-
4977
var value *string
5078
if len(kvSplit) == 2 {
5179
value = &kvSplit[1]
5280
}
5381

54-
argMap[key] = value
82+
args[key] = kernelArg{
83+
position: uint(index),
84+
key: key,
85+
value: value,
86+
}
5587
}
5688

57-
return argMap
89+
return args
5890
}

machine.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ func (m *Machine) setupKernelArgs(ctx context.Context) error {
504504
// Validation that we are not overriding an existing "ip=" setting happens in the network validation
505505
if staticIPInterface := m.Cfg.NetworkInterfaces.staticIPInterface(); staticIPInterface != nil {
506506
ipBootParam := staticIPInterface.StaticConfiguration.IPConfiguration.ipBootParam()
507-
kernelArgs["ip"] = &ipBootParam
507+
kernelArgs.Add("ip", &ipBootParam)
508508
}
509509

510510
m.Cfg.KernelArgs = kernelArgs.String()
@@ -649,7 +649,7 @@ func (m *Machine) startVMM(ctx context.Context) error {
649649
return nil
650650
}
651651

652-
//StopVMM stops the current VMM.
652+
// StopVMM stops the current VMM.
653653
func (m *Machine) StopVMM() error {
654654
return m.stopVMM()
655655
}

0 commit comments

Comments
 (0)