Skip to content

Commit 9d885f6

Browse files
authored
Merge pull request #79 from mzbenami/mbenami/outputfield-action
add output:field action
2 parents f1b2397 + 20d25a7 commit 9d885f6

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

ovs/action.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ var (
6464

6565
// errMoveEmpty is returned when Move is called with src and/or dst set to the empty string.
6666
errMoveEmpty = errors.New("src and/or dst field for action move are empty")
67+
68+
// errOutputFieldEmpty is returned when OutputField is called with field set to the empty string.
69+
errOutputFieldEmpty = errors.New("field for action output (output:field syntax) is empty")
6770
)
6871

6972
// Action strings in lower case, as those are compared to the lower case letters
@@ -184,6 +187,7 @@ const (
184187
patModTransportSourcePort = "mod_tp_src:%d"
185188
patModVLANVID = "mod_vlan_vid:%d"
186189
patOutput = "output:%d"
190+
patOutputField = "output:%s"
187191
patResubmitPort = "resubmit:%s"
188192
patResubmitPortTable = "resubmit(%s,%s)"
189193
)
@@ -403,6 +407,34 @@ func (a *outputAction) GoString() string {
403407
return fmt.Sprintf("ovs.Output(%d)", a.port)
404408
}
405409

410+
// OutputField outputs the packet to the switch port described by the specified field.
411+
// For example, when the `field` value is "in_port", the packet is output to the port
412+
// it came in on.
413+
func OutputField(field string) Action {
414+
return &outputFieldAction{
415+
field: field,
416+
}
417+
}
418+
419+
// An outputFieldAction is an Action which is used by OutputField.
420+
type outputFieldAction struct {
421+
field string
422+
}
423+
424+
// MarshalText implements Action.
425+
func (a *outputFieldAction) MarshalText() ([]byte, error) {
426+
if a.field == "" {
427+
return nil, errOutputFieldEmpty
428+
}
429+
430+
return bprintf(patOutputField, a.field), nil
431+
}
432+
433+
// GoString implements Action.
434+
func (a *outputFieldAction) GoString() string {
435+
return fmt.Sprintf("ovs.OutputField(%q)", a.field)
436+
}
437+
406438
// Conjunction associates a flow with a certain conjunction ID to match on more than
407439
// one dimension across multiple set matches.
408440
func Conjunction(id int, dimensionNumber int, dimensionSize int) Action {

ovs/action_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,46 @@ func TestMove(t *testing.T) {
627627
})
628628
}
629629
}
630+
631+
func TestOutputField(t *testing.T) {
632+
var tests = []struct {
633+
desc string
634+
a Action
635+
action string
636+
err error
637+
}{
638+
{
639+
desc: "output field OK",
640+
a: OutputField("in_port"),
641+
action: "output:in_port",
642+
},
643+
{
644+
desc: "empty field",
645+
a: OutputField(""),
646+
err: errOutputFieldEmpty,
647+
},
648+
}
649+
650+
for _, tt := range tests {
651+
t.Run(tt.desc, func(t *testing.T) {
652+
action, err := tt.a.MarshalText()
653+
654+
if want, got := tt.err, err; want != got {
655+
t.Fatalf("unexpected error:\n- want: %v\n- got: %v",
656+
want, got)
657+
}
658+
if err != nil {
659+
return
660+
}
661+
662+
if want, got := tt.action, string(action); want != got {
663+
t.Fatalf("unexpected Action:\n- want: %q\n- got: %q",
664+
want, got)
665+
}
666+
})
667+
}
668+
}
669+
630670
func TestActionGoString(t *testing.T) {
631671
tests := []struct {
632672
a Action
@@ -704,6 +744,10 @@ func TestActionGoString(t *testing.T) {
704744
a: Move("nw_src", "nw_dst"),
705745
s: `ovs.Move("nw_src", "nw_dst")`,
706746
},
747+
{
748+
a: OutputField("in_port"),
749+
s: `ovs.OutputField("in_port")`,
750+
},
707751
}
708752

709753
for _, tt := range tests {

0 commit comments

Comments
 (0)