Rod Hynes 6 лет назад
Родитель
Сommit
46dd567810

+ 21 - 21
psiphon/common/parameters/bpf.go

@@ -75,134 +75,134 @@ func (s *BPFProgramSpec) Assemble() ([]bpf.RawInstruction, error) {
 // BPFInstructionSpec represents a golang.org/x/net/bpf.Instruction and can be
 // marshaled.
 type BPFInstructionSpec struct {
-	Name        string
-	Instruction json.RawMessage
+	Op   string
+	Args json.RawMessage
 }
 
 // GetInstruction coverts a BPFInstructionSpec to the equivilent
 // golang.org/x/net/bpf.Instruction.
 func (s *BPFInstructionSpec) GetInstruction() (bpf.Instruction, error) {
-	switch s.Name {
+	switch s.Op {
 	case "ALUOpConstant":
 		var instruction bpf.ALUOpConstant
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "ALUOpX":
 		var instruction bpf.ALUOpX
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "Jump":
 		var instruction bpf.Jump
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "JumpIf":
 		var instruction bpf.JumpIf
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "JumpIfX":
 		var instruction bpf.JumpIfX
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "LoadAbsolute":
 		var instruction bpf.LoadAbsolute
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "LoadConstant":
 		var instruction bpf.LoadConstant
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "LoadExtension":
 		var instruction bpf.LoadExtension
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "LoadIndirect":
 		var instruction bpf.LoadIndirect
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "LoadMemShift":
 		var instruction bpf.LoadMemShift
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "LoadScratch":
 		var instruction bpf.LoadScratch
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "NegateA":
 		var instruction bpf.NegateA
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "RetA":
 		var instruction bpf.RetA
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "RetConstant":
 		var instruction bpf.RetConstant
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "StoreScratch":
 		var instruction bpf.StoreScratch
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "TAX":
 		var instruction bpf.TAX
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	case "TXA":
 		var instruction bpf.TXA
-		err := json.Unmarshal(s.Instruction, &instruction)
+		err := json.Unmarshal(s.Args, &instruction)
 		if err != nil {
 			return nil, errors.Trace(err)
 		}
 		return instruction, nil
 	}
 
-	return nil, errors.Tracef("unknown bpf instruction: %s", s.Name)
+	return nil, errors.Tracef("unknown bpf instruction: %s", s.Op)
 }

+ 1 - 1
psiphon/dialParameters.go

@@ -324,7 +324,7 @@ func MakeDialParameters(
 	}
 
 	if (!isReplay || !replayBPF) &&
-		supportsBPF() &&
+		ClientBPFEnabled() &&
 		protocol.TunnelProtocolUsesTCP(dialParams.TunnelProtocol) {
 
 		if p.WeightedCoinFlip(parameters.BPFClientTCPProbability) {

+ 1 - 1
psiphon/net_android_linux.go

@@ -29,7 +29,7 @@ import (
 	"golang.org/x/sys/unix"
 )
 
-func supportsBPF() bool {
+func ClientBPFEnabled() bool {
 	return true
 }
 

+ 1 - 1
psiphon/net_darwin.go

@@ -26,7 +26,7 @@ import (
 	"golang.org/x/net/bpf"
 )
 
-func supportsBPF() bool {
+func ClientBPFEnabled() bool {
 	return false
 }
 

+ 1 - 1
psiphon/net_other.go

@@ -26,7 +26,7 @@ import (
 	"golang.org/x/net/bpf"
 )
 
-func supportsBPF() bool {
+func ClientBPFEnabled() bool {
 	return false
 }
 

+ 6 - 1
psiphon/server/bpf.go

@@ -36,6 +36,11 @@ import (
 	"golang.org/x/sys/unix"
 )
 
+// ServerBPFEnabled indicates if BPF functionality is enabled.
+func ServerBPFEnabled() bool {
+	return true
+}
+
 // newTCPListenerWithBPF creates a TCP net.Listener, optionally attaching
 // the BPF program specified by the tactics parameter BPFServerTCPProgram.
 func newTCPListenerWithBPF(
@@ -93,7 +98,7 @@ func getBPFProgram(support *SupportServices) (bool, string, []bpf.RawInstruction
 		return false, "", nil, errors.Trace(err)
 	}
 
-	if tactics != nil {
+	if tactics == nil {
 		// This server isn't configured with tactics.
 		return false, "", nil, nil
 	}

+ 5 - 0
psiphon/server/bpf_unsupported.go

@@ -27,6 +27,11 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
 )
 
+// ServerBPFEnabled indicates if BPF functionality is enabled.
+func ServerBPFEnabled() bool {
+	return false
+}
+
 func newTCPListenerWithBPF(
 	_ *SupportServices, localAddress string) (net.Listener, string, error) {
 

+ 39 - 4
psiphon/server/server_test.go

@@ -1121,7 +1121,7 @@ func runServer(t *testing.T, runConfig *runServerConfig) {
 
 	select {
 	case logFields := <-serverConnectedLog:
-		err := checkExpectedLogFields(runConfig, logFields)
+		err := checkExpectedLogFields(runConfig, false, false, logFields)
 		if err != nil {
 			t.Fatalf("invalid server connected log fields: %s", err)
 		}
@@ -1129,9 +1129,12 @@ func runServer(t *testing.T, runConfig *runServerConfig) {
 		t.Fatalf("missing server connected log")
 	}
 
+	expectClientBPFField := psiphon.ClientBPFEnabled() && doClientTactics
+	expectServerBPFField := ServerBPFEnabled() && doServerTactics
+
 	select {
 	case logFields := <-serverTunnelLog:
-		err := checkExpectedLogFields(runConfig, logFields)
+		err := checkExpectedLogFields(runConfig, expectClientBPFField, expectServerBPFField, logFields)
 		if err != nil {
 			t.Fatalf("invalid server tunnel log fields: %s", err)
 		}
@@ -1143,7 +1146,11 @@ func runServer(t *testing.T, runConfig *runServerConfig) {
 	checkPruneServerEntriesTest(t, runConfig, testDataDirName, pruneServerEntryTestCases)
 }
 
-func checkExpectedLogFields(runConfig *runServerConfig, fields map[string]interface{}) error {
+func checkExpectedLogFields(
+	runConfig *runServerConfig,
+	expectClientBPFField bool,
+	expectServerBPFField bool,
+	fields map[string]interface{}) error {
 
 	// Limitations:
 	//
@@ -1299,6 +1306,24 @@ func checkExpectedLogFields(runConfig *runServerConfig, fields map[string]interf
 		}
 	}
 
+	if expectClientBPFField {
+		name := "client_bpf"
+		if fields[name] == nil {
+			return fmt.Errorf("missing expected field '%s'", name)
+		} else if fmt.Sprintf("%s", fields[name]) != "test-client-bpf" {
+			return fmt.Errorf("unexpected field value %s: '%s'", name, fields[name])
+		}
+	}
+
+	if expectServerBPFField {
+		name := "server_bpf"
+		if fields[name] == nil {
+			return fmt.Errorf("missing expected field '%s'", name)
+		} else if fmt.Sprintf("%s", fields[name]) != "test-server-bpf" {
+			return fmt.Errorf("unexpected field value %s: '%s'", name, fields[name])
+		}
+	}
+
 	return nil
 }
 
@@ -1823,7 +1848,17 @@ func paveTacticsConfigFile(
           "LivenessTestMinUpstreamBytes" : %d,
           "LivenessTestMaxUpstreamBytes" : %d,
           "LivenessTestMinDownstreamBytes" : %d,
-          "LivenessTestMaxDownstreamBytes" : %d
+          "LivenessTestMaxDownstreamBytes" : %d,
+          "BPFServerTCPProgram": {
+            "Name" : "test-server-bpf",
+              "Instructions" : [
+                {"Op": "RetConstant", "Args": {"Val": 65535}}]},
+          "BPFServerTCPProbability" : 1.0,
+          "BPFClientTCPProgram": {
+            "Name" : "test-client-bpf",
+              "Instructions" : [
+                {"Op": "RetConstant", "Args": {"Val": 65535}}]},
+          "BPFClientTCPProbability" : 1.0
         }
       },
       "FilteredTactics" : [