Skip to content

Commit

Permalink
Add mmds version 2 support (#441)
Browse files Browse the repository at this point in the history
Closes #437

Signed-off-by: Mathis Joffre <[email protected]>
  • Loading branch information
Joffref authored Aug 31, 2022
1 parent c007a0c commit 226c8ef
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 2 deletions.
2 changes: 1 addition & 1 deletion handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func NewSetMetadataHandler(metadata interface{}) Handler {
var ConfigMmdsHandler = Handler{
Name: ConfigMmdsHandlerName,
Fn: func(ctx context.Context, m *Machine) error {
return m.setMmdsConfig(ctx, m.Cfg.MmdsAddress, m.Cfg.NetworkInterfaces)
return m.setMmdsConfig(ctx, m.Cfg.MmdsAddress, m.Cfg.NetworkInterfaces, m.Cfg.MmdsVersion)
},
}

Expand Down
1 change: 1 addition & 0 deletions handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ func TestHandlers(t *testing.T) {
mmdsConfig := &models.MmdsConfig{
IPV4Address: String(mmdsAddress.String()),
NetworkInterfaces: []string{"1"},
Version: String(string(MMDSv1)),
}

cases := []struct {
Expand Down
20 changes: 19 additions & 1 deletion machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ type SeccompConfig struct {
// be started again.
var ErrAlreadyStarted = errors.New("firecracker: machine already started")

type MMDSVersion string

const (
MMDSv1 = MMDSVersion("V1")
MMDSv2 = MMDSVersion("V2")
)

// Config is a collection of user-configurable VMM settings
type Config struct {
// SocketPath defines the file path where the Firecracker control socket
Expand Down Expand Up @@ -152,6 +159,10 @@ type Config struct {
// If not provided, the default address (169.254.169.254) will be used.
MmdsAddress net.IP

// MmdsVersion is the MMDS version to use.
// If not provided, the default version (1) will be used.
MmdsVersion MMDSVersion

// Configuration for snapshot loading
Snapshot SnapshotConfig
}
Expand Down Expand Up @@ -907,8 +918,15 @@ func (m *Machine) sendCtrlAltDel(ctx context.Context) error {
return err
}

func (m *Machine) setMmdsConfig(ctx context.Context, address net.IP, ifaces NetworkInterfaces) error {
func (m *Machine) setMmdsConfig(ctx context.Context, address net.IP, ifaces NetworkInterfaces, version MMDSVersion) error {
var mmdsCfg models.MmdsConfig
// MMDS config supports v1 and v2, v1 is going to be deprecated.
// Default to the version 1 if no version is specified
if version == MMDSv1 || version == MMDSv2 {
mmdsCfg.Version = String(string(version))
} else {
mmdsCfg.Version = String(string(MMDSv1))
}
if address != nil {
mmdsCfg.IPV4Address = String(address.String())
}
Expand Down
94 changes: 94 additions & 0 deletions machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,100 @@ func TestWaitForSocket(t *testing.T) {
}
}

func TestMicroVMExecutionWithMmdsV2(t *testing.T) {
fctesting.RequiresKVM(t)

var nCpus int64 = 2
cpuTemplate := models.CPUTemplate(models.CPUTemplateT2)
var memSz int64 = 256

dir, err := ioutil.TempDir("", t.Name())
require.NoError(t, err)
defer os.RemoveAll(dir)

socketPath := filepath.Join(dir, "TestMicroVMExecution.sock")
logFifo := filepath.Join(dir, "firecracker.log")
metricsFifo := filepath.Join(dir, "firecracker-metrics")
capturedLog := filepath.Join(dir, "writer.fifo")
fw, err := os.OpenFile(capturedLog, os.O_CREATE|os.O_RDWR, 0600)
require.NoError(t, err, "failed to open fifo writer file")
defer fw.Close()

vmlinuxPath := getVmlinuxPath(t)

networkIfaces := []NetworkInterface{{
StaticConfiguration: &StaticNetworkConfiguration{
MacAddress: "01-23-45-67-89-AB-CD-EF",
HostDevName: "tap0",
},
}}

cfg := Config{
SocketPath: socketPath,
LogFifo: logFifo,
MetricsFifo: metricsFifo,
LogLevel: "Debug",
MachineCfg: models.MachineConfiguration{
VcpuCount: Int64(nCpus),
CPUTemplate: cpuTemplate,
MemSizeMib: Int64(memSz),
Smt: Bool(false),
},
DisableValidation: true,
NetworkInterfaces: networkIfaces,
FifoLogWriter: fw,
MmdsVersion: MMDSv2,
}

ctx := context.Background()
cmd := VMCommandBuilder{}.
WithSocketPath(socketPath).
WithBin(getFirecrackerBinaryPath()).
Build(ctx)

m, err := NewMachine(ctx, cfg, WithProcessRunner(cmd), WithLogger(fctesting.NewLogEntry(t)))
if err != nil {
t.Fatalf("failed to create new machine: %v", err)
}

m.Handlers.Validation = m.Handlers.Validation.Clear()

vmmCtx, vmmCancel := context.WithTimeout(ctx, 30*time.Second)
defer vmmCancel()
exitchannel := make(chan error)
go func() {
err := m.startVMM(vmmCtx)
if err != nil {
exitchannel <- err
close(exitchannel)
return
}
defer m.StopVMM()

exitchannel <- m.Wait(vmmCtx)
close(exitchannel)
}()

deadlineCtx, deadlineCancel := context.WithTimeout(vmmCtx, 250*time.Millisecond)
defer deadlineCancel()
if err := waitForAliveVMM(deadlineCtx, m.client); err != nil {
t.Fatal(err)
}

t.Run("TestCreateMachine", func(t *testing.T) { testCreateMachine(ctx, t, m) })
t.Run("TestCreateBootSource", func(t *testing.T) { testCreateBootSource(ctx, t, m, vmlinuxPath) })
t.Run("TestCreateNetworkInterface", func(t *testing.T) { testCreateNetworkInterfaceByID(ctx, t, m) })
t.Run("TestAttachRootDrive", func(t *testing.T) { testAttachRootDrive(ctx, t, m) })
t.Run("SetMetadata", func(t *testing.T) { testSetMetadata(ctx, t, m) })
t.Run("UpdateMetadata", func(t *testing.T) { testUpdateMetadata(ctx, t, m) })
t.Run("GetMetadata", func(t *testing.T) { testGetMetadata(ctx, t, m) }) // Should be after testSetMetadata and testUpdateMetadata

// unconditionally stop the VM here. TestShutdown may have triggered a shutdown, but if it
// didn't for some reason, we still need to terminate it:
err = m.StopVMM()
assert.NoError(t, err, "failed to stop VM")
}

func testSetMetadata(ctx context.Context, t *testing.T, m *Machine) {
metadata := map[string]string{"key": "value"}
err := m.SetMetadata(ctx, metadata)
Expand Down

0 comments on commit 226c8ef

Please sign in to comment.