[VOL-2616]:
- Replicate the flow across all pbits if vlan pcp is not coming as
part of openflow. Otherwise, only pbit 0 traffic is allowed via
BAL.
- This is compatible with openolt agent version 2.1.2 and beyond.
2.1.2 openolt agent version will be released as part of
https://gerrit.opencord.org/#/c/17601/.
Change-Id: Iec5f5a2fca41e74e1f7f0d2f83149345027b5f18
diff --git a/adaptercore/openolt_flowmgr.go b/adaptercore/openolt_flowmgr.go
index 578861d..b79e4bd 100644
--- a/adaptercore/openolt_flowmgr.go
+++ b/adaptercore/openolt_flowmgr.go
@@ -24,6 +24,7 @@
"encoding/json"
"fmt"
"math/big"
+ "strings"
"sync"
"time"
@@ -167,6 +168,11 @@
NoneUniID = -1
//NoneGemPortID constant
NoneGemPortID = -1
+
+ // BinaryStringPrefix is binary string prefix
+ BinaryStringPrefix = "0b"
+ // BinaryBit1 is binary bit 1 expressed as a character
+ BinaryBit1 = '1'
)
type gemPortKey struct {
@@ -726,12 +732,12 @@
log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
"action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
"logicalFlow": *logicalFlow})
- var vlanPbit uint32
+ var vlanPbit uint32 = 0xff // means no pbit
if _, ok := classifier[VlanPcp]; ok {
vlanPbit = classifier[VlanPcp].(uint32)
log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
} else {
- log.Debugw("bpit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
+ log.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
}
flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
@@ -952,7 +958,7 @@
}
// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
-func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32, classifier map[string]interface{}, action map[string]interface{}) error {
+func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) error {
log.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfID, "onuId": onuID, "portNo": portNo, "allocId": allocID, "gemPortId": gemPortID, "vlanId": vlanID, "flow": logicalFlow})
uplinkClassifier := make(map[string]interface{})
@@ -1047,12 +1053,11 @@
classifier.IVid = vid
}
}
+ // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
- if vlanPcp == 0 {
- classifier.OPbits = VlanPCPMask
- } else {
- classifier.OPbits = vlanPcp & VlanPCPMask
- }
+ classifier.OPbits = vlanPcp
+ } else {
+ classifier.OPbits = VlanPCPMask
}
classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
@@ -2353,23 +2358,40 @@
portNo uint32, classifier map[string]interface{}, action map[string]interface{},
logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32) error,
f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
+ classifier map[string]interface{}, action map[string]interface{},
logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
- classifier map[string]interface{}, action map[string]interface{}) error,
+ ) error,
args map[string]uint32,
classifier map[string]interface{}, action map[string]interface{},
logicalFlow *ofp.OfpFlowStats,
gemPorts []uint32,
+ TpInst *tp.TechProfile,
FlowType string,
vlanID ...uint32) {
log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
- for _, gemPortID := range gemPorts {
- if FlowType == HsiaFlow || FlowType == DhcpFlow {
- 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"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
- } else {
- log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
- return
+
+ 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 {
+ log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
+ return
+ }
+ }
}
}
}
@@ -2592,7 +2614,7 @@
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, DhcpFlow)
+ installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow)
}
} else if ipProto == IgmpProto {
@@ -2604,7 +2626,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, IgmpFlow)
+ installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow)
}
} else {
log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
@@ -2624,9 +2646,9 @@
tp_pb.Direction_UPSTREAM,
pcp.(uint32))
- f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
+ f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID)
} else {
- installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
+ installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, vlanID)
}
}
} else if _, ok := actionInfo[PushVlan]; ok {
@@ -2639,7 +2661,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, HsiaFlow)
+ installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
}
} else if _, ok := actionInfo[PopVlan]; ok {
log.Info("Adding Downstream data rule")
@@ -2651,7 +2673,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, HsiaFlow)
+ installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
}
} else {
log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})