VOL-3614 Created multicast GEM If is_multicast flag is enable into tech profile
Change-Id: I82f680df0c2a51841965c484ae3398a1606b2739
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index 0f44d84..70b5f67 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -19,7 +19,9 @@
import (
"context"
+ "encoding/binary"
"fmt"
+ "net"
"strconv"
"time"
@@ -82,13 +84,17 @@
)
type ponAniGemPortAttribs struct {
- gemPortID uint16
- upQueueID uint16
- downQueueID uint16
- direction uint8
- qosPolicy string
- weight uint8
- pbitString string
+ gemPortID uint16
+ upQueueID uint16
+ downQueueID uint16
+ direction uint8
+ qosPolicy string
+ weight uint8
+ pbitString string
+ isMulticast bool
+ multicastGemID uint16
+ staticACL string
+ dynamicACL string
}
//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
@@ -361,6 +367,12 @@
loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
loGemPortAttribs.weight = gemEntry.queueWeight
loGemPortAttribs.pbitString = gemEntry.pbitString
+ if gemEntry.isMulticast {
+ loGemPortAttribs.isMulticast = true
+ loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
+ loGemPortAttribs.staticACL = gemEntry.staticACL
+ loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
+ }
logger.Debugw("prio-related GemPort attributes:", log.Fields{
"gemPortID": loGemPortAttribs.gemPortID,
@@ -368,6 +380,10 @@
"downQueueID": loGemPortAttribs.downQueueID,
"pbitString": loGemPortAttribs.pbitString,
"prioQueueIndex": gemEntry.prioQueueIndex,
+ "isMulticast": loGemPortAttribs.isMulticast,
+ "multicastGemID": loGemPortAttribs.multicastGemID,
+ "staticACL": loGemPortAttribs.staticACL,
+ "dynamicACL": loGemPortAttribs.dynamicACL,
})
oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
@@ -513,7 +529,7 @@
}
}
- var foundIwPtr bool = false
+ var foundIwPtr = false
for index, value := range loPrioGemPortArray {
if value != 0 {
foundIwPtr = true
@@ -942,26 +958,52 @@
"EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
"SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
"device-id": oFsm.deviceID})
- meParams := me.ParamData{
- EntityID: gemPortAttribs.gemPortID,
- Attributes: me.AttributeValueMap{
- "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
- "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
- "ServiceProfilePointer": oFsm.mapperSP0ID,
- "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
- "GalProfilePointer": galEthernetEID,
- },
- }
- meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
- oFsm.pAdaptFsm.commChan, meParams)
- //accept also nil as (error) return value for writing to LastTx
- // - this avoids misinterpretation of new received OMCI messages
- oFsm.pLastTxMeInstance = meInstance
+ //TODO if the port has only downstream direction the isMulticast flag can be removed.
+ if gemPortAttribs.isMulticast {
+ ipv4MulticastTable := make([]uint8, 12)
+ binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.gemPortID)
+ binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
+ // This is the 224.0.0.1 address
+ binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4allsys))
+ // this is the 255.255.255.255 address
+ binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4bcast))
+
+ meParams := me.ParamData{
+ EntityID: gemPortAttribs.gemPortID,
+ Attributes: me.AttributeValueMap{
+ "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID,
+ "InterworkingOption": 0, // Don't Care
+ "ServiceProfilePointer": 0, // Don't Care
+ "GalProfilePointer": galEthernetEID,
+ "Ipv4MulticastAddressTable": ipv4MulticastTable,
+ },
+ }
+ meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout,
+ true, oFsm.pAdaptFsm.commChan, meParams)
+ oFsm.pLastTxMeInstance = meInstance
+
+ } else {
+ meParams := me.ParamData{
+ EntityID: gemPortAttribs.gemPortID,
+ Attributes: me.AttributeValueMap{
+ "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
+ "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
+ "ServiceProfilePointer": oFsm.mapperSP0ID,
+ "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
+ "GalProfilePointer": galEthernetEID,
+ },
+ }
+ meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, meParams)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ oFsm.pLastTxMeInstance = meInstance
+ }
//verify response
err := oFsm.waitforOmciResponse()
if err != nil {
- logger.Errorw("GemIwTp create failed, aborting AniConfig FSM!",
+ logger.Errorw("GemTP create failed, aborting AniConfig FSM!",
log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
_ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
return
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
index 102f32d..1ab6c0b 100644
--- a/internal/pkg/onuadaptercore/onu_uni_tp.go
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -22,6 +22,7 @@
"encoding/json"
"errors"
"fmt"
+ "strconv"
"strings"
"sync"
@@ -73,6 +74,11 @@
queueSchedPolicy string
queueWeight uint8
removeIndex uint16
+ isMulticast bool
+ //TODO check if this has any value/difference from gemPortId
+ multicastGemPortID uint16
+ staticACL string
+ dynamicACL string
}
//refers to one tcont and its properties and all assigned GemPorts and their properties
@@ -267,7 +273,7 @@
}
/* internal methods *********************/
-
+// nolint: gocyclo
func (onuTP *onuUniTechProf) readAniSideConfigFromTechProfile(
ctx context.Context, aUniID uint8, aTpID uint8, aPathString string, aProcessingStep uint8) {
var tpInst tp.TechProfile
@@ -383,6 +389,8 @@
loGemPortRead = true
} else {
//for all further GemPorts we need to extend the mapGemPortParams
+ //FIXME one can use uint16(content.GemportID) as key to the map
+ // see jira https://jira.opencord.org/browse/VOL-3667
onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(pos)] = &gemPortParamStruct{}
}
onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(pos)].gemPortID =
@@ -391,7 +399,7 @@
// for now just assume bidirectional (upstream never exists alone)
onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(pos)].direction = 3 //as defined in G.988
// expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
- if 7 < content.PriorityQueue {
+ if content.PriorityQueue > 7 {
logger.Errorw("PonAniConfig reject on GemPortList - PrioQueue value invalid",
log.Fields{"device-id": onuTP.deviceID, "index": pos, "PrioQueue": content.PriorityQueue})
//remove PonAniConfig as done so far, delete map should be safe, even if not existing
@@ -416,6 +424,58 @@
onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(pos)].queueWeight =
uint8(content.Weight)
}
+
+ for pos, downstreamContent := range tpInst.DownstreamGemPortAttributeList {
+ if uint32(pos) == loNumGemPorts {
+ logger.Debugw("PonAniConfig abort GemPortList - GemList exceeds set NumberOfGemPorts",
+ log.Fields{"device-id": onuTP.deviceID, "index": pos, "NumGem": loNumGemPorts})
+ break
+ }
+
+ //Flag is defined as string in the TP in voltha-lib-go, parsing it from string
+ isMulticast, err := strconv.ParseBool(downstreamContent.IsMulticast)
+
+ if err != nil {
+ logger.Errorw("multicast-error-config-unknown-flag-in-technology-profile", log.Fields{"UniTpKey": uniTPKey,
+ "downstream-gem": downstreamContent, "error": err})
+ continue
+ }
+
+ if isMulticast {
+ mcastGemID := uint16(downstreamContent.McastGemID)
+ _, existing := onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID]
+ if existing {
+ //GEM port was previously configured, avoid setting multicast attributes
+ logger.Errorw("multicast-error-config-existing-gem-port-config", log.Fields{"UniTpKey": uniTPKey,
+ "downstream-gem": downstreamContent, "key": mcastGemID})
+ continue
+ } else {
+ //GEM port is not configured, setting multicast attributes
+ logger.Infow("creating-multicast-gem-port", log.Fields{"uniPtKEy": uniTPKey,
+ "gemPortId": mcastGemID, "key": mcastGemID})
+
+ //for all further GemPorts we need to extend the mapGemPortParams
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID] = &gemPortParamStruct{}
+
+ //Separate McastGemId is derived from OMCI-lib-go, if not needed first needs to be removed there.
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].gemPortID = mcastGemID
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].direction = 2 // for ANI to UNI as defined in G.988
+ //Downstream Priority Queue is set in the data of any message exchanged, using in mcast too.
+ if downstreamContent.PriorityQueue > 7 {
+ logger.Errorw("PonAniConfig reject on GemPortList - PrioQueue value invalid",
+ log.Fields{"device-id": onuTP.deviceID, "index": pos, "PrioQueue": downstreamContent.PriorityQueue})
+ }
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].prioQueueIndex =
+ uint8(downstreamContent.PriorityQueue)
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].isMulticast = isMulticast
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].multicastGemPortID =
+ uint16(downstreamContent.McastGemID)
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].staticACL = downstreamContent.SControlList
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].dynamicACL = downstreamContent.DControlList
+ }
+ }
+ }
+
if !loGemPortRead {
logger.Errorw("PonAniConfig reject - no GemPort could be read from TechProfile",
log.Fields{"path": aPathString, "device-id": onuTP.deviceID})
@@ -424,8 +484,6 @@
onuTP.chTpConfigProcessingStep <- 0 //error indication
return
}
- //TODO!! MC (downstream) GemPorts can be set using DownstreamGemPortAttributeList separately
-
//logger does not simply output the given structures, just give some example debug values
logger.Debugw("PonAniConfig read from TechProfile", log.Fields{
"device-id": onuTP.deviceID, "uni-id": aUniID,
diff --git a/internal/pkg/onuadaptercore/openonu_utils.go b/internal/pkg/onuadaptercore/openonu_utils.go
index aa7de95..0db62ed 100644
--- a/internal/pkg/onuadaptercore/openonu_utils.go
+++ b/internal/pkg/onuadaptercore/openonu_utils.go
@@ -18,7 +18,9 @@
package adaptercoreonu
import (
+ "encoding/binary"
"errors"
+ "net"
"regexp"
"strconv"
"strings"
@@ -41,3 +43,11 @@
// Atoi returns uint64 and need to be type-casted to uint8 as tpID is uint8 size.
return uint8(tpID), err
}
+
+//IPToInt32 transforms an IP of net.Ip type to int32
+func IPToInt32(ip net.IP) uint32 {
+ if len(ip) == 16 {
+ return binary.BigEndian.Uint32(ip[12:16])
+ }
+ return binary.BigEndian.Uint32(ip)
+}