[VOL-2774] Allow not filtering the pbit values for the TT workflow

Change-Id: I64b991143b7654807af10359ba67fab0af7b76a1
diff --git a/VERSION b/VERSION
index 8e8299d..6cdfe8d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.4.2
+2.4.3-dev
diff --git a/internal/pkg/core/openolt_flowmgr.go b/internal/pkg/core/openolt_flowmgr.go
index 07469d7..9640251 100644
--- a/internal/pkg/core/openolt_flowmgr.go
+++ b/internal/pkg/core/openolt_flowmgr.go
@@ -733,18 +733,23 @@
 		"action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
 		"logicalFlow": *logicalFlow})
 	var vlanPbit uint32 = 0xff // means no pbit
+	var vlanVid uint32
 	if _, ok := classifier[VlanPcp]; ok {
 		vlanPbit = classifier[VlanPcp].(uint32)
 		logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
 	} else {
 		logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
 	}
+	if _, ok := classifier[VlanVid]; ok {
+		vlanVid = classifier[VlanVid].(uint32)
+		log.Debugw("Found vlan in the flow", log.Fields{"VlanVid": vlanVid})
+	}
 	flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
 	if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
 		logger.Debug("flow-already-exists")
 		return nil
 	}
-	flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
+	flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
 	if err != nil {
 		return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
 	}
@@ -753,7 +758,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
 	}
 	logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(action)
+	actionProto, err := makeOpenOltActionField(action, classifier)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
 	}
@@ -837,7 +842,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
 	}
 	logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(action)
+	actionProto, err := makeOpenOltActionField(action, classifier)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
 	}
@@ -922,7 +927,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
 	}
 	logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(action)
+	actionProto, err := makeOpenOltActionField(action, classifier)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
 	}
@@ -968,6 +973,7 @@
 	uplinkClassifier[EthType] = uint32(EapEthType)
 	uplinkClassifier[PacketTagType] = SingleTag
 	uplinkClassifier[VlanVid] = vlanID
+	uplinkClassifier[VlanPcp] = classifier[VlanPcp]
 	// Fill action
 	uplinkAction[TrapToHost] = true
 	flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
@@ -976,7 +982,7 @@
 		return nil
 	}
 	//Add Uplink EAPOL Flow
-	uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
+	uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
 	if err != nil {
 		return olterrors.NewErrNotFound("flow-id", log.Fields{
 			"interface-id": intfID,
@@ -991,7 +997,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
 	}
 	logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(uplinkAction)
+	actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
 	}
@@ -1078,16 +1084,31 @@
 	return &classifier, nil
 }
 
-func makeOpenOltActionField(actionInfo map[string]interface{}) (*openoltpb2.Action, error) {
+func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
 	var actionCmd openoltpb2.ActionCmd
 	var action openoltpb2.Action
 	action.Cmd = &actionCmd
 	if _, ok := actionInfo[PopVlan]; ok {
-		action.OVid = actionInfo[VlanVid].(uint32)
 		action.Cmd.RemoveOuterTag = true
+		if _, ok := actionInfo[VlanPcp]; ok {
+			action.Cmd.RemarkInnerPbits = true
+			action.IPbits = actionInfo[VlanPcp].(uint32)
+			if _, ok := actionInfo[VlanVid]; ok {
+				action.Cmd.TranslateInnerTag = true
+				action.IVid = actionInfo[VlanVid].(uint32)
+			}
+		}
 	} else if _, ok := actionInfo[PushVlan]; ok {
 		action.OVid = actionInfo[VlanVid].(uint32)
 		action.Cmd.AddOuterTag = true
+		if _, ok := actionInfo[VlanPcp]; ok {
+			action.OPbits = actionInfo[VlanPcp].(uint32)
+			action.Cmd.RemarkOuterPbits = true
+			if _, ok := classifierInfo[VlanVid]; ok {
+				action.IVid = classifierInfo[VlanVid].(uint32)
+				action.Cmd.TranslateInnerTag = true
+			}
+		}
 	} else if _, ok := actionInfo[TrapToHost]; ok {
 		action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
 	} else {
@@ -1347,7 +1368,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
 	}
 	logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(actionInfo)
+	actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
 	}
@@ -2418,35 +2439,60 @@
 	gemPorts []uint32,
 	TpInst *tp.TechProfile,
 	FlowType string,
+	direction string,
 	vlanID ...uint32) {
 	logger.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
 
-	for _, gemPortAttribute := range TpInst.UpstreamGemPortAttributeList {
-		var gemPortID uint32
-		// The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
-		// We need to trim prefix "0b", before further processing
-		// Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
-		// in the string is set to binary bit 1 (expressed as char '1' in the binary string).
-		for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
-			// If a particular character in the string is set to '1', identify the index of this character from
-			// the LSB position which marks the PCP bit consumed by the given gem port.
-			// This PCP bit now becomes a classifier in the flow.
-			if pbitSet == BinaryBit1 {
-				classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
-				gemPortID = gemPortAttribute.GemportID
-				if FlowType == HsiaFlow || FlowType == DhcpFlow || FlowType == IgmpFlow {
-					f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
-				} else if FlowType == EapolFlow {
-					f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
-				} else {
-					logger.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
-					return
+	// The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
+	// We need to trim prefix "0b", before further processing
+	// Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
+	// in the string is set to binary bit 1 (expressed as char '1' in the binary string).
+
+	// If a particular character in the string is set to '1', identify the index of this character from
+	// the LSB position which marks the PCP bit consumed by the given gem port.
+	// This PCP bit now becomes a classifier in the flow.
+
+	attributes := TpInst.DownstreamGemPortAttributeList
+	if direction == Upstream {
+		attributes = TpInst.UpstreamGemPortAttributeList
+	}
+
+	for _, gemPortAttribute := range attributes {
+		if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
+			continue
+		}
+		gemPortID := gemPortAttribute.GemportID
+		if allPbitsMarked(gemPortAttribute.PbitMap) {
+			classifier[VlanPcp] = uint32(VlanPCPMask)
+			if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
+				f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
+			} else if FlowType == EapolFlow {
+				f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
+			}
+		} else {
+			for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
+				if pbitSet == BinaryBit1 {
+					classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
+					if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
+						f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
+					} else if FlowType == EapolFlow {
+						f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
+					}
 				}
 			}
 		}
 	}
 }
 
+func allPbitsMarked(pbitMap string) bool {
+	for pos, pBit := range pbitMap {
+		if pos >= 2 && pBit != BinaryBit1 {
+			return false
+		}
+	}
+	return true
+}
+
 func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
 	logger.Debug("Adding trap-dhcp-of-nni-flow")
 	action := make(map[string]interface{})
@@ -2480,7 +2526,7 @@
 		logger.Debug("Flow-exists-not-re-adding")
 		return nil
 	}
-	flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
+	flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
 	if err != nil {
 		return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id", log.Fields{
 			"interface-id": networkInterfaceID,
@@ -2495,7 +2541,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
 	}
 	logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(action)
+	actionProto, err := makeOpenOltActionField(action, classifier)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
 	}
@@ -2601,7 +2647,7 @@
 		return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
 	}
 	logger.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
-	actionProto, err := makeOpenOltActionField(action)
+	actionProto, err := makeOpenOltActionField(action, classifier)
 	if err != nil {
 		return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
 	}
@@ -2662,10 +2708,11 @@
 					tp_pb.Direction_UPSTREAM,
 					pcp.(uint32))
 				//Adding DHCP upstream flow
+
 				f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
 			} else {
 				//Adding DHCP upstream flow to all gemports
-				installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow)
+				installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream)
 			}
 
 		} else if ipProto == IgmpProto {
@@ -2677,7 +2724,7 @@
 				f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
 			} else {
 				//Adding IGMP upstream flow to all gem ports
-				installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow)
+				installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream)
 			}
 		} else {
 			logger.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
@@ -2699,7 +2746,7 @@
 
 				f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID)
 			} else {
-				installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, vlanID)
+				installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, vlanID)
 			}
 		}
 	} else if _, ok := actionInfo[PushVlan]; ok {
@@ -2712,7 +2759,7 @@
 			f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
 		} else {
 			//Adding HSIA upstream flow to all gemports
-			installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
+			installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream)
 		}
 	} else if _, ok := actionInfo[PopVlan]; ok {
 		logger.Info("Adding Downstream data rule")
@@ -2724,7 +2771,7 @@
 			f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
 		} else {
 			//Adding HSIA downstream flow to all gemports
-			installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
+			installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream)
 		}
 	} else {
 		logger.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
diff --git a/internal/pkg/resourcemanager/resourcemanager.go b/internal/pkg/resourcemanager/resourcemanager.go
index f61c1f8..3ed7441 100755
--- a/internal/pkg/resourcemanager/resourcemanager.go
+++ b/internal/pkg/resourcemanager/resourcemanager.go
@@ -506,7 +506,7 @@
 func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ctx context.Context, ponIntfID uint32, ONUID int32, uniID int32,
 	gemportID uint32,
 	flowStoreCookie uint64,
-	flowCategory string, vlanPcp ...uint32) (uint32, error) {
+	flowCategory string, vlanVid uint32, vlanPcp ...uint32) (uint32, error) {
 
 	var err error
 	FlowPath := fmt.Sprintf("%d,%d,%d", ponIntfID, ONUID, uniID)
@@ -519,8 +519,10 @@
 		logger.Debugw("Found flowId(s) for this ONU", log.Fields{"pon": ponIntfID, "ONUID": ONUID, "uniID": uniID, "KVpath": FlowPath})
 		for _, flowID := range FlowIDs {
 			FlowInfo := RsrcMgr.GetFlowIDInfo(ctx, ponIntfID, int32(ONUID), int32(uniID), uint32(flowID))
-			er := getFlowIDFromFlowInfo(FlowInfo, flowID, gemportID, flowStoreCookie, flowCategory, vlanPcp...)
+			er := getFlowIDFromFlowInfo(FlowInfo, flowID, gemportID, flowStoreCookie, flowCategory, vlanVid, vlanPcp...)
 			if er == nil {
+				log.Debugw("Found flowid for the vlan, pcp, and gem",
+					log.Fields{"flowID": flowID, "vlanVid": vlanVid, "vlanPcp": vlanPcp, "gemPortID": gemportID})
 				return flowID, er
 			}
 		}
@@ -1017,14 +1019,16 @@
 	return nil
 }
 
-func getFlowIDFromFlowInfo(FlowInfo *[]FlowInfo, flowID, gemportID uint32, flowStoreCookie uint64, flowCategory string, vlanPcp ...uint32) error {
+func getFlowIDFromFlowInfo(FlowInfo *[]FlowInfo, flowID, gemportID uint32, flowStoreCookie uint64, flowCategory string,
+	vlanVid uint32, vlanPcp ...uint32) error {
 	if FlowInfo != nil {
 		for _, Info := range *FlowInfo {
 			if int32(gemportID) == Info.Flow.GemportId && flowCategory != "" && Info.FlowCategory == flowCategory {
 				logger.Debug("Found flow matching with flow category", log.Fields{"flowId": flowID, "FlowCategory": flowCategory})
-				if Info.FlowCategory == "HSIA_FLOW" && Info.Flow.Classifier.OPbits == vlanPcp[0] {
-					logger.Debug("Found matching vlan pcp ", log.Fields{"flowId": flowID, "Vlanpcp": vlanPcp[0]})
-					return nil
+				if Info.FlowCategory == "HSIA_FLOW" {
+					if err := checkVlanAndPbitEqualityForFlows(vlanVid, Info, vlanPcp[0]); err == nil {
+						return nil
+					}
 				}
 			}
 			if int32(gemportID) == Info.Flow.GemportId && flowStoreCookie != 0 && Info.FlowStoreCookie == flowStoreCookie {
@@ -1039,6 +1043,33 @@
 	return errors.New("invalid flow-info")
 }
 
+func checkVlanAndPbitEqualityForFlows(vlanVid uint32, Info FlowInfo, vlanPcp uint32) error {
+	if err := checkVlanEqualityForFlows(vlanVid, Info); err != nil {
+		return err
+	}
+
+	//flow has remark action and pbits
+	if Info.Flow.Action.Cmd.RemarkInnerPbits || Info.Flow.Action.Cmd.RemarkOuterPbits {
+		if vlanPcp == Info.Flow.Action.OPbits || vlanPcp == Info.Flow.Action.IPbits {
+			return nil
+		}
+	} else if vlanPcp == Info.Flow.Classifier.OPbits {
+		//no remark action but flow has pbits
+		return nil
+	} else if vlanPcp == 0xff || Info.Flow.Classifier.OPbits == 0xff {
+		// no pbit found
+		return nil
+	}
+	return errors.New("not found in terms of pbit equality")
+}
+
+func checkVlanEqualityForFlows(vlanVid uint32, Info FlowInfo) error {
+	if vlanVid == Info.Flow.Action.OVid || vlanVid == Info.Flow.Classifier.IVid {
+		return nil
+	}
+	return errors.New("not found in terms of vlan_id equality")
+}
+
 //AddGemToOnuGemInfo adds gemport to onugem info kvstore
 func (RsrcMgr *OpenOltResourceMgr) AddGemToOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) error {
 	var onuGemData []OnuGemInfo
diff --git a/internal/pkg/resourcemanager/resourcemanager_test.go b/internal/pkg/resourcemanager/resourcemanager_test.go
index 4786940..18074cc 100644
--- a/internal/pkg/resourcemanager/resourcemanager_test.go
+++ b/internal/pkg/resourcemanager/resourcemanager_test.go
@@ -528,6 +528,7 @@
 		gemportID       uint32
 		flowStoreCookie uint64
 		flowCategory    string
+		vlanVid         uint32
 		vlanPcp         []uint32
 	}
 	tests := []struct {
@@ -538,14 +539,14 @@
 		wantErr error
 	}{
 		{"GetFlowID-1", getResMgr(), args{1, 2, 2, 2, 2,
-			"HSIA", nil}, 0, errors.New("failed to get flows")},
+			"HSIA", 33, nil}, 0, errors.New("failed to get flows")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			RsrcMgr := testResMgrObject(tt.fields)
 			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 			defer cancel()
-			got, err := RsrcMgr.GetFlowID(ctx, tt.args.ponIntfID, tt.args.ONUID, tt.args.uniID, tt.args.gemportID, tt.args.flowStoreCookie, tt.args.flowCategory, tt.args.vlanPcp...)
+			got, err := RsrcMgr.GetFlowID(ctx, tt.args.ponIntfID, tt.args.ONUID, tt.args.uniID, tt.args.gemportID, tt.args.flowStoreCookie, tt.args.flowCategory, tt.args.vlanVid, tt.args.vlanPcp...)
 			if err != nil && reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) {
 				t.Errorf("GetFlowID() error = %v, wantErr %v", err, tt.wantErr)
 				return
@@ -969,6 +970,7 @@
 		gemportID       uint32
 		flowStoreCookie uint64
 		flowCategory    string
+		vlanVid         uint32
 		vlanPcp         []uint32
 	}
 	flowInfo := &[]FlowInfo{
@@ -978,7 +980,15 @@
 				GemportId: 1,
 				Classifier: &openolt.Classifier{
 					OPbits: 1,
-				}},
+					OVid:   33,
+				},
+				Action: &openolt.Action{
+					Cmd: &openolt.ActionCmd{
+						AddOuterTag: true,
+					},
+					OVid: 7,
+				},
+			},
 			1,
 			"HSIA_FLOW",
 			2000,
@@ -986,6 +996,14 @@
 		{
 			&openolt.Flow{
 				GemportId: 1,
+				Classifier: &openolt.Classifier{
+					OVid: 0,
+				},
+				Action: &openolt.Action{
+					Cmd: &openolt.ActionCmd{
+						TrapToHost: true,
+					},
+				},
 			},
 			1,
 			"EAPOL",
@@ -999,13 +1017,13 @@
 	}{
 		{"getFlowIdFromFlowInfo-1", args{}, errors.New("invalid flow-info")},
 		{"getFlowIdFromFlowInfo-2", args{flowInfo, 1, 1, 1,
-			"HSIA_FLOW", []uint32{1, 2}}, errors.New("invalid flow-info")},
+			"HSIA_FLOW", 33, []uint32{1, 2}}, errors.New("invalid flow-info")},
 		{"getFlowIdFromFlowInfo-2", args{flowInfo, 1, 1, 1,
-			"EAPOL", []uint32{1, 2}}, errors.New("invalid flow-info")},
+			"EAPOL", 33, []uint32{1, 2}}, errors.New("invalid flow-info")},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			err := getFlowIDFromFlowInfo(tt.args.FlowInfo, tt.args.flowID, tt.args.gemportID, tt.args.flowStoreCookie, tt.args.flowCategory, tt.args.vlanPcp...)
+			err := getFlowIDFromFlowInfo(tt.args.FlowInfo, tt.args.flowID, tt.args.gemportID, tt.args.flowStoreCookie, tt.args.flowCategory, tt.args.vlanVid, tt.args.vlanPcp...)
 			if reflect.TypeOf(err) != reflect.TypeOf(tt.wantErr) && err != nil {
 				t.Errorf("getFlowIDFromFlowInfo() error = %v, wantErr %v", err, tt.wantErr)
 			}