fpga_crihook: check if requested AF is programmed

Check if programmed AF id is equal to the requested AF id
after re-programming a device.
This commit is contained in:
Ed Bartosh 2018-07-18 11:27:40 +03:00
parent 9df1afdf43
commit b1b2edf1b8
4 changed files with 95 additions and 52 deletions

View File

@ -189,6 +189,16 @@ func (he *hookEnv) programBitStream(params *fpgaParams, fpgaBitStreamPath string
if err != nil { if err != nil {
return fmt.Errorf("failed to program AFU %s to region %s: error: %v, output: %s", params.afu, params.region, err, string(output)) return fmt.Errorf("failed to program AFU %s to region %s: error: %v, output: %s", params.afu, params.region, err, string(output))
} }
programmedAfu, err := he.getProgrammedAfu(params.devNum)
if err != nil {
return err
}
if programmedAfu != params.afu {
return fmt.Errorf("programmed function %s instead of %s", programmedAfu, params.afu)
}
return nil return nil
} }

View File

@ -243,36 +243,61 @@ func TestValidateBitstream(t *testing.T) {
} }
} }
func genFpgaConfAction(he *hookEnv, afuIDTemplate string, returnError bool) fakeexec.FakeCombinedOutputAction {
return func() ([]byte, error) {
if returnError {
return []byte("error"), &fakeexec.FakeExitError{Status: 1}
}
he.afuIDTemplate = afuIDTemplate // emulate reprogramming
return []byte(""), nil
}
}
func TestProgramBitStream(t *testing.T) { func TestProgramBitStream(t *testing.T) {
tcases := []struct { tcases := []struct {
params *fpgaParams params *fpgaParams
expectedErr bool afuIDTemplate string
fakeAction []fakeexec.FakeCombinedOutputAction newAFUIDTemplate string
expectedErr bool
fpgaconfErr bool
}{ }{
{ {
params: &fpgaParams{ params: &fpgaParams{
devNum: "0",
region: "ce48969398f05f33946d560708be108a", region: "ce48969398f05f33946d560708be108a",
afu: "f7df405cbd7acf7222f144b0b93acd18"}, afu: "f7df405cbd7acf7222f144b0b93acd18"},
expectedErr: false, afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_d8424dc4a4a3c413f89e433683f9040b",
fakeAction: []fakeexec.FakeCombinedOutputAction{ newAFUIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_f7df405cbd7acf7222f144b0b93acd18",
func() ([]byte, error) { return []byte(""), nil }, },
}, {
params: &fpgaParams{"", "", ""},
expectedErr: true,
fpgaconfErr: true,
}, },
{ {
params: &fpgaParams{ params: &fpgaParams{
devNum: "0",
region: "ce48969398f05f33946d560708be108a", region: "ce48969398f05f33946d560708be108a",
afu: "f7df405cbd7acf7222f144b0b93acd18"}, afu: "d8424dc4a4a3c413f89e433683f9040b"},
expectedErr: true, afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/doesnt_exist",
fakeAction: []fakeexec.FakeCombinedOutputAction{ expectedErr: true,
func() ([]byte, error) { return []byte("error"), &fakeexec.FakeExitError{Status: 1} }, },
}, {
params: &fpgaParams{
devNum: "0",
region: "ce48969398f05f33946d560708be108a",
afu: "d8424dc4a4a3c413f89e433683f9040b"},
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_f7df405cbd7acf7222f144b0b93acd18",
newAFUIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_f7df405cbd7acf7222f144b0b93acd18",
expectedErr: true,
}, },
} }
for _, tc := range tcases { for _, tc := range tcases {
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeAction} he := newHookEnv("", "", nil, tc.afuIDTemplate)
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))} actions := []fakeexec.FakeCombinedOutputAction{genFpgaConfAction(he, tc.newAFUIDTemplate, tc.fpgaconfErr)}
he := newHookEnv("", "", &execer, "") fcmd := fakeexec.FakeCmd{CombinedOutputScript: actions}
he.execer = &fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
err := he.programBitStream(tc.params, "") err := he.programBitStream(tc.params, "")
if err != nil && !tc.expectedErr { if err != nil && !tc.expectedErr {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
@ -282,34 +307,38 @@ func TestProgramBitStream(t *testing.T) {
func TestProcess(t *testing.T) { func TestProcess(t *testing.T) {
tcases := []struct { tcases := []struct {
stdinJSON string stdinJSON string
configJSON string configJSON string
afuIDTemplate string params *fpgaParams
expectedErr bool afuIDTemplate string
fakeCombinedOutputAction []fakeexec.FakeCombinedOutputAction newAFUIDTemplate string
expectedErr bool
fpgaconfErr bool
gbsInfoAction fakeexec.FakeCombinedOutputAction
}{ }{
{ {
params: &fpgaParams{
devNum: "0",
region: "ce48969398f05f33946d560708be108a",
afu: "d8424dc4a4a3c413f89e433683f9040b"},
stdinJSON: "stdin-correct.json", stdinJSON: "stdin-correct.json",
configJSON: "config-correct.json", configJSON: "config-correct.json",
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_already_programmed", afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_f7df405cbd7acf7222f144b0b93acd18",
expectedErr: false, gbsInfoAction: func() ([]byte, error) {
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{ return ioutil.ReadFile("testdata/gbs-info-correct.json")
func() ([]byte, error) {
return ioutil.ReadFile("testdata/gbs-info-correct.json")
},
func() ([]byte, error) { return []byte(""), nil },
}, },
}, },
{ {
stdinJSON: "stdin-correct.json", params: &fpgaParams{
configJSON: "config-correct.json", devNum: "0",
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet", region: "ce48969398f05f33946d560708be108a",
expectedErr: false, afu: "f7df405cbd7acf7222f144b0b93acd18"},
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{ stdinJSON: "stdin-correct.json",
func() ([]byte, error) { configJSON: "config-correct.json",
return ioutil.ReadFile("testdata/gbs-info-correct.json") afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_d8424dc4a4a3c413f89e433683f9040b",
}, newAFUIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_f7df405cbd7acf7222f144b0b93acd18",
func() ([]byte, error) { return []byte(""), nil }, gbsInfoAction: func() ([]byte, error) {
return ioutil.ReadFile("testdata/gbs-info-correct.json")
}, },
}, },
{ {
@ -331,7 +360,7 @@ func TestProcess(t *testing.T) {
{ {
stdinJSON: "stdin-correct.json", stdinJSON: "stdin-correct.json",
configJSON: "config-no-afu.json", configJSON: "config-no-afu.json",
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet", afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_d8424dc4a4a3c413f89e433683f9040b",
expectedErr: true, expectedErr: true,
}, },
{ {
@ -342,30 +371,29 @@ func TestProcess(t *testing.T) {
{ {
stdinJSON: "stdin-correct.json", stdinJSON: "stdin-correct.json",
configJSON: "config-non-existing-bitstream.json", configJSON: "config-non-existing-bitstream.json",
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet", afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_d8424dc4a4a3c413f89e433683f9040b",
expectedErr: true, expectedErr: true,
}, },
{ {
stdinJSON: "stdin-correct.json", stdinJSON: "stdin-correct.json",
configJSON: "config-correct.json", configJSON: "config-correct.json",
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet", afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_d8424dc4a4a3c413f89e433683f9040b",
expectedErr: true, expectedErr: true,
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{ gbsInfoAction: func() ([]byte, error) {
func() ([]byte, error) { return ioutil.ReadFile("testdata/gbs-info-no-accelerator-type-uuid.json")
return ioutil.ReadFile("testdata/gbs-info-no-accelerator-type-uuid.json")
},
}, },
}, },
{ {
params: &fpgaParams{
devNum: "0",
region: "ce48969398f05f33946d560708be108a",
afu: "d8424dc4a4a3c413f89e433683f9040b"},
stdinJSON: "stdin-correct.json", stdinJSON: "stdin-correct.json",
configJSON: "config-correct.json", configJSON: "config-correct.json",
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet", afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_d8424dc4a4a3c413f89e433683f9040b",
expectedErr: true, expectedErr: true,
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{ gbsInfoAction: func() ([]byte, error) {
func() ([]byte, error) { return ioutil.ReadFile("testdata/gbs-info-correct.json")
return ioutil.ReadFile("testdata/gbs-info-correct.json")
},
func() ([]byte, error) { return []byte("error"), &fakeexec.FakeExitError{Status: 1} },
}, },
}, },
} }
@ -376,10 +404,15 @@ func TestProcess(t *testing.T) {
t.Fatalf("can't open file %s: %v", tc.stdinJSON, err) t.Fatalf("can't open file %s: %v", tc.stdinJSON, err)
} }
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeCombinedOutputAction} he := newHookEnv("testdata/intel.com/fpga", tc.configJSON, nil, tc.afuIDTemplate)
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
actions := []fakeexec.FakeCombinedOutputAction{
tc.gbsInfoAction,
genFpgaConfAction(he, tc.newAFUIDTemplate, tc.fpgaconfErr),
}
fcmd := fakeexec.FakeCmd{CombinedOutputScript: actions}
he.execer = &fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
he := newHookEnv("testdata/intel.com/fpga", tc.configJSON, &execer, tc.afuIDTemplate)
err = he.process(stdin) err = he.process(stdin)
if err != nil && !tc.expectedErr { if err != nil && !tc.expectedErr {