UNI port is derived from tunnelID and some bug fixes
Flow-manager now uses tunnel id to derive uniport needed for futher flow processing
Able to verify EAPOL/HSIA flows end to end with physical hardware ( Edgecore BAL OLT & TWSH ONT kit) with below work-around :
EAPOL flow from logical device , results in installing device flows in ONU device (due to default leaf device flows in core - leafDeviceDefaultRules),
This flow over-rides previously installed default 4091 private rule installed from techprofile download event , Hence removed default leaf flows in rw_core to overcome this problem.
Change-Id: Icdb96674545e1c58ea3f020f989a3c9dd06214bc
diff --git a/adaptercore/device_handler.go b/adaptercore/device_handler.go
index f077eef..3bb34db 100644
--- a/adaptercore/device_handler.go
+++ b/adaptercore/device_handler.go
@@ -130,6 +130,10 @@
}
// portNum := IntfIdToPortNo(intfId,portType)
portNum := intfId
+ if portType == voltha.Port_ETHERNET_NNI {
+ portNum = IntfIdToPortNo(intfId, portType)
+ }
+ // portNum := IntfIdToPortNo(intfId,portType)
label := GetportLabel(portNum, portType)
if len(label) == 0 {
log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
diff --git a/adaptercore/olt_platform.go b/adaptercore/olt_platform.go
index 60b9bb8..131234a 100644
--- a/adaptercore/olt_platform.go
+++ b/adaptercore/olt_platform.go
@@ -79,6 +79,8 @@
var MIN_UPSTREAM_PORT_ID = 0xfffd
var MAX_UPSTREAM_PORT_ID = 0xfffffffd
+var controllerPorts []uint32 = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
+
func MkUniPortNum(intfId uint32, onuId uint32, uniId uint32) uint32 {
/* TODO: Add checks */
return ((intfId << 11) | (onuId << 4) | uniId)
@@ -145,11 +147,22 @@
}
func IsUpstream(outPort uint32) bool {
- if (outPort >= uint32(MIN_UPSTREAM_PORT_ID)) && (outPort <= uint32(MAX_UPSTREAM_PORT_ID)) {
- return true
+ for _, port := range controllerPorts {
+ if port == outPort {
+ return true
+ }
}
if (outPort & (1 << 16)) == (1 << 16) {
return true
}
return false
}
+
+func IsControllerBoundFlow(outPort uint32) bool {
+ for _, port := range controllerPorts {
+ if port == outPort {
+ return true
+ }
+ }
+ return false
+}
diff --git a/adaptercore/openolt_flowmgr.go b/adaptercore/openolt_flowmgr.go
index 1112151..0b8120b 100644
--- a/adaptercore/openolt_flowmgr.go
+++ b/adaptercore/openolt_flowmgr.go
@@ -26,11 +26,11 @@
tp "github.com/opencord/voltha-go/common/techprofile"
fd "github.com/opencord/voltha-go/rw_core/flow_decomposition"
rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
+ ic "github.com/opencord/voltha-protos/go/inter_container"
ofp "github.com/opencord/voltha-protos/go/openflow_13"
- "math/big"
- // ic "github.com/opencord/voltha-protos/go/inter_container"
openolt_pb2 "github.com/opencord/voltha-protos/go/openolt"
voltha "github.com/opencord/voltha-protos/go/voltha"
+ "math/big"
)
const (
@@ -61,18 +61,19 @@
DOUBLE_TAG = "double_tag"
// classifierInfo
- ETH_TYPE = "eth_type"
- TPID = "tpid"
- IP_PROTO = "ip_proto"
- IN_PORT = "in_port"
- VLAN_VID = "vlan_vid"
- VLAN_PCP = "vlan_pcp"
- UDP_DST = "udp_dst"
- UDP_SRC = "udp_src"
- IPV4_DST = "ipv4_dst"
- IPV4_SRC = "ipv4_src"
- METADATA = "metadata"
- OUTPUT = "output"
+ ETH_TYPE = "eth_type"
+ TPID = "tpid"
+ IP_PROTO = "ip_proto"
+ IN_PORT = "in_port"
+ VLAN_VID = "vlan_vid"
+ VLAN_PCP = "vlan_pcp"
+ UDP_DST = "udp_dst"
+ UDP_SRC = "udp_src"
+ IPV4_DST = "ipv4_dst"
+ IPV4_SRC = "ipv4_src"
+ METADATA = "metadata"
+ TUNNEL_ID = "tunnel_id"
+ OUTPUT = "output"
// Action
POP_VLAN = "pop_vlan"
PUSH_VLAN = "push_vlan"
@@ -209,7 +210,7 @@
UniId: uniId,
PortNo: uniPort,
Tconts: tconts}); err != nil {
- log.Error("Error while creating TCONT in device")
+ log.Errorw("Error while creating TCONT in device", log.Fields{"error": err})
return nil, nil
}
allocID = append(allocID, tech_profile_instance.UsScheduler.AllocID)
@@ -274,6 +275,7 @@
downlinkClassifier[PACKET_TAG_TYPE] = DOUBLE_TAG
log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
"downlinkAction": downlinkAction})
+ // Ignore private VLAN flow given by decomposer, cannot do anything with this flow
if uint32(downlinkClassifier[METADATA].(uint64)) == MkUniPortNum(intfId, onuId, uniId) &&
downlinkClassifier[VLAN_VID] == (uint32(ofp.OfpVlanId_OFPVID_PRESENT)|4000) {
log.Infow("EAPOL DL flow , Already added ,ignoring it", log.Fields{"downlinkClassifier": downlinkClassifier,
@@ -643,36 +645,27 @@
return hash.Uint64()
}
-func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]openolt_pb2.Flow {
- var flows []openolt_pb2.Flow
- /* FIXME: To be removed and identify way to get same flow ID for HSIA DL and UL flows
- To get existing flow matching flow catogery or cookie
- */
- /*flow.Category = flowCategory
- flow.FlowStoreCookie = flowStoreCookie*/
- flows = append(flows, *flow)
- // Get existing flow for flowid from KV store
- //existingFlows := f.resourceMgr.GetFlowIDInfo(uint32(flow.AccessIntfId),uint32(flow.OnuId),uint32(flow.UniId),flow.FlowId)
- /*existingFlows := nil
- if existingFlows != nil{
- log.Debugw("Flow exists for given flowID, appending it",log.Fields{"flowID":flow.FlowId})
- for _,f := range *existingFlows{
- flows = append(flows,f)
- }
- }*/
- log.Debugw("Updated flows for given flowID", log.Fields{"updatedflow": flows, "flowid": flow.FlowId})
+func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
+ var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
+ // Get existing flow for flowid for given subscriber from KV store
+ existingFlows := f.resourceMgr.GetFlowIDInfo(uint32(flow.AccessIntfId), uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
+ if existingFlows != nil {
+ log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
+ for _, f := range *existingFlows {
+ flows = append(flows, f)
+ }
+ }
+ log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
return &flows
}
-func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfId int32, onuId int32, uniId int32, flowId uint32, flows *[]openolt_pb2.Flow) error {
- log.Debugw("Storing flow into KV store", log.Fields{"flows": *flows})
- /* FIXME: To implement API in resource mgr and invoke */
- /*if err := f.resourceMgr.UpdateFlowIDInfo(intfId,onuId,uniId,flowId,flows); err != nil{
- log.Debug("Error while Storing flow into KV store")
- return err
- }
- log.Info("Stored flow into KV store successfully!")
- */
+func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfId int32, onuId int32, uniId int32, flowId uint32, flows *[]rsrcMgr.FlowInfo) error {
+ log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
+ if err := f.resourceMgr.UpdateFlowIDInfo(intfId, onuId, uniId, flowId, flows); err != nil {
+ log.Debug("Error while Storing flow into KV store")
+ return err
+ }
+ log.Info("Stored flow(s) into KV store successfully!")
return nil
}
@@ -777,6 +770,9 @@
} else if field.Type == fd.METADATA {
classifierInfo[METADATA] = field.GetTableMetadata()
log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
+ } else if field.Type == fd.TUNNEL_ID {
+ classifierInfo[TUNNEL_ID] = field.GetTunnelId()
+ log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TUNNEL_ID].(uint64)})
} else {
log.Errorw("Un supported field type", log.Fields{"type": field.Type})
return
@@ -792,11 +788,6 @@
return
}
} else if action.Type == fd.POP_VLAN {
- /*if gotoTable := fd.GetGotoTableId(flow); gotoTable == 0 {
- log.Infow("action-type-pop-vlan, being taken care of by ONU", log.Fields{"flow": flow})
- actionInfo[POP_VLAN] = false
- return
- }*/
actionInfo[POP_VLAN] = true
log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[IN_PORT].(uint32)})
} else if action.Type == fd.PUSH_VLAN {
@@ -837,31 +828,43 @@
return
}
}
- /*if gotoTable := fd.GetGotoTableId(flow); gotoTable != 0 {
- if actionInfo[POP_VLAN] == nil {
- log.Infow("Go to table - action-type-pop-vlan, being taken care of by ONU", log.Fields{"flow": flow})
- return
- }
- }*/
- /* NOTE: This condition will be false when core decompose and provides flows to respective devices separately */
- /* if _,ok := actionInfo[OUTPUT]; ok == false{
- log.Debug("action-go-to-table, get next flow for outport details")
- if _, ok := classifierInfo[METADATA]; ok {
- if next_flow := findNextFlow(flow); next_flow == nil {
- log.Debugw("No next flow found ", log.Fields{"classifier": classifierInfo, "flow": flow})
- return
+ /* Controller bound trap flows */
+ if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
+ log.Debug("Controller bound trap flows, getting inport from tunnelid")
+ /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
+ if portType := IntfIdToPortTypeName(classifierInfo[IN_PORT].(uint32)); portType == voltha.Port_PON_OLT {
+ if uniPort := fd.GetChildPortFromTunnelId(flow); uniPort != 0 {
+ classifierInfo[IN_PORT] = uniPort
+ log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[IN_PORT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
} else {
- actionInfo[OUTPUT] = fd.GetOutPort(next_flow)
- log.Debugw("action-next-flow-outport", log.Fields{"actionInfo[OUTPUT]": actionInfo[OUTPUT].(uint32)})
- for _, field := range fd.GetOfbFields(next_flow) {
- if field.Type == fd.VLAN_VID {
- classifierInfo[METADATA] = field.GetVlanVid() & 0xfff
- log.Debugw("next-flow-classifier-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
- }
- }
+ log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
+ return
}
}
- }*/
+ } else {
+ log.Debug("Non-Controller flows, getting uniport from tunnelid")
+ // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
+ if portType := IntfIdToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
+ if uniPort := fd.GetChildPortFromTunnelId(flow); uniPort != 0 {
+ actionInfo[OUTPUT] = uniPort
+ log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
+ } else {
+ log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[IN_PORT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
+ return
+ }
+ // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
+ } else if portType := IntfIdToPortTypeName(classifierInfo[IN_PORT].(uint32)); portType == voltha.Port_PON_OLT {
+ if uniPort := fd.GetChildPortFromTunnelId(flow); uniPort != 0 {
+ classifierInfo[IN_PORT] = uniPort
+ log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
+ "outport": actionInfo[OUTPUT].(uint32)})
+ } else {
+ log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[IN_PORT].(uint32),
+ "outPort": actionInfo[OUTPUT].(uint32)})
+ return
+ }
+ }
+ }
log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[IN_PORT], "action_output": actionInfo[OUTPUT]})
portNo, intfId, onuId, uniId := ExtractAccessFromFlow(classifierInfo[IN_PORT].(uint32), actionInfo[OUTPUT].(uint32))
f.divideAndAddFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow)
@@ -875,26 +878,23 @@
return err
}
log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
- /* TODO: uncomment once voltha-proto is ready with changes */
- /*
- tpPath := f.getTPpath(intfId, uni)
- tpDownloadMsg := &ic.TechProfileDownload{UniId: uniId, Path: tpPath}
- var tpDownloadMsg interface{}
- log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter",log.Fields{"msg": *tpDownloadMsg})
- sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
- tpDownloadMsg,
- //ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
- ic.InterAdapterMessageType_OMCI_REQUEST,
- f.deviceHandler.deviceType,
- onuDevice.Type,
- onuDevice.Id,
- onuDevice.ProxyAddress.DeviceId, "")
- if sendErr != nil {
- log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
- "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
- "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
- return sendErr
- }
- log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter",log.Fields{"msg":tpDownloadMsg})*/
+
+ tpPath := f.getTPpath(intfId, uni)
+ tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniId, Path: tpPath}
+ log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
+ sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
+ tpDownloadMsg,
+ ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
+ f.deviceHandler.deviceType,
+ onuDevice.Type,
+ onuDevice.Id,
+ onuDevice.ProxyAddress.DeviceId, "")
+ if sendErr != nil {
+ log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
+ "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
+ "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
+ return sendErr
+ }
+ log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
return nil
}