VOL-4625: Support for FTTB flows in openolt adapter
Change-Id: Icdf3c66f310f68101e8a84ef272ed38b849d77bf
diff --git a/internal/pkg/core/openolt_flowmgr.go b/internal/pkg/core/openolt_flowmgr.go
index 8b24630..06ad2c0 100644
--- a/internal/pkg/core/openolt_flowmgr.go
+++ b/internal/pkg/core/openolt_flowmgr.go
@@ -91,6 +91,8 @@
EthType = "eth_type"
//EthDst constant
EthDst = "eth_dst"
+ //EthSrc constant
+ EthSrc = "eth_src"
//TPID constant
TPID = "tpid"
//IPProto constant
@@ -978,28 +980,38 @@
}
func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
- flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
+ flowContext.classifier[PacketTagType] = SingleTag
+ // extract the cvid/inner-vid from the write metadata
+ writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
+ if writeMetadata != 0 {
+ // Writemetadata field is 8 bytes
+ // cvid is on the outer most two bytes of the write metadata
+ cvid := (writeMetadata & 0xffff000000000000) >> 48
+ // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
+ if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
+ flowContext.classifier[PacketTagType] = DoubleTag
+ }
+ }
logger.Debugw(ctx, "adding-upstream-data-flow",
log.Fields{
"uplinkClassifier": flowContext.classifier,
"uplinkAction": flowContext.action})
return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
- /* TODO: Install Secondary EAP on the subscriber vlan */
}
func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
downlinkClassifier := flowContext.classifier
downlinkAction := flowContext.action
-
- // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
- // Per some deployment models, it is also possible that ONU operates on double tagged packets,
- // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
- // Need a better way for detection of packet tag type from OpenFlow message.
- if _, ok := downlinkClassifier[VlanVid]; !ok {
- downlinkClassifier[PacketTagType] = SingleTag
- } else {
- downlinkClassifier[PacketTagType] = DoubleTag
- downlinkAction[PopVlan] = true
+ // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
+ downlinkClassifier[PacketTagType] = SingleTag
+ // extract the cvid/inner-vid from the write metadata
+ writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
+ if writeMetadata != 0 {
+ // Writemetadata field is 8 bytes
+ // cvid is on the outer most two bytes of the write metadata
+ if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
+ downlinkClassifier[PacketTagType] = DoubleTag
+ }
}
logger.Debugw(ctx, "adding-downstream-data-flow",
log.Fields{
@@ -1022,10 +1034,14 @@
}
}
- // vlan_vid is a uint32. must be type asserted as such or conversion fails
- dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
- if ok {
- downlinkAction[VlanVid] = dlClVid & 0xfff
+ // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
+ // The matched vlan is the one that is getting popped.
+ if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
+ // vlan_vid is a uint32. must be type asserted as such or conversion fails
+ dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
+ if ok {
+ downlinkAction[VlanVid] = dlClVid & 0xfff
+ }
}
return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
@@ -1464,6 +1480,7 @@
classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
+ classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
classifier.PktTagType = pktTagType
@@ -1483,28 +1500,38 @@
var action openoltpb2.Action
action.Cmd = &actionCmd
if _, ok := actionInfo[PopVlan]; ok {
+ // Pop outer vid
action.Cmd.RemoveOuterTag = true
if _, ok := actionInfo[VlanPcp]; ok {
+ // Remark inner pbit
action.Cmd.RemarkInnerPbits = true
action.IPbits = actionInfo[VlanPcp].(uint32)
if _, ok := actionInfo[VlanVid]; ok {
+ // Remark inner vid
action.Cmd.TranslateInnerTag = true
action.IVid = actionInfo[VlanVid].(uint32)
}
}
} else if _, ok := actionInfo[PushVlan]; ok {
+ // push outer vid
action.OVid = actionInfo[VlanVid].(uint32)
action.Cmd.AddOuterTag = true
if _, ok := actionInfo[VlanPcp]; ok {
+ // translate outer pbit
action.OPbits = actionInfo[VlanPcp].(uint32)
action.Cmd.RemarkOuterPbits = true
if _, ok := classifierInfo[VlanVid]; ok {
+ // translate inner vid
action.IVid = classifierInfo[VlanVid].(uint32)
action.Cmd.TranslateInnerTag = true
}
}
} else if _, ok := actionInfo[TrapToHost]; ok {
action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
+ } else if _, ok := actionInfo[VlanVid]; ok {
+ // Translate outer vid
+ action.Cmd.TranslateOuterTag = true
+ action.OVid = actionInfo[VlanVid].(uint32)
}
// When OLT is transparent to vlans no-action is valid.
/*
@@ -2965,7 +2992,10 @@
logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
} else if field.Type == flows.ETH_DST {
classifierInfo[EthDst] = field.GetEthDst()
- logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
+ logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
+ } else if field.Type == flows.ETH_SRC {
+ classifierInfo[EthSrc] = field.GetEthSrc()
+ logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
} else if field.Type == flows.IP_PROTO {
classifierInfo[IPProto] = field.GetIpProto()
logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
diff --git a/internal/pkg/core/openolt_flowmgr_test.go b/internal/pkg/core/openolt_flowmgr_test.go
index 218ecf5..0c94e94 100644
--- a/internal/pkg/core/openolt_flowmgr_test.go
+++ b/internal/pkg/core/openolt_flowmgr_test.go
@@ -1203,6 +1203,16 @@
kwTable0Meter1["meter_id"] = 1
kwTable0Meter1["write_metadata"] = 0x4000000000 // Tech-Profile-ID 64
+ kwTable0Meter1WithCvid := make(map[string]uint64)
+ kwTable0Meter1WithCvid["table_id"] = 0
+ kwTable0Meter1WithCvid["meter_id"] = 1
+ kwTable0Meter1WithCvid["write_metadata"] = 0x3c004000000000 // Tech-Profile-ID 64, cvid 60 in write metadata
+
+ kwTable1Meter1WithCvid := make(map[string]uint64)
+ kwTable1Meter1WithCvid["table_id"] = 1
+ kwTable1Meter1WithCvid["meter_id"] = 1
+ kwTable1Meter1WithCvid["write_metadata"] = 0x3c004000000000 // Tech-Profile-ID 64, cvid 60 in write metadata
+
flowMetadata1 := ofp.FlowMetadata{Meters: []*ofp.OfpMeterConfig{
{
Flags: 5,
@@ -1388,6 +1398,37 @@
},
KV: kwTable1Meter1,
}
+
+ // Downstream FTTB Subscriber flow - ONU1 UNI0 PON0, write metadata with cvid
+ // match outer vid 100, with inner cvid 60 -> modify outer vid to 200 and output on pon port
+ fa9 := &fu.FlowArgs{
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(16777216),
+ fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT | 100)),
+ fu.TunnelId(256),
+ },
+ Actions: []*ofp.OfpAction{
+ fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT | 200))),
+ fu.Output(536870912),
+ },
+ KV: kwTable0Meter1WithCvid,
+ }
+
+ // Upstream FTTB Subscriber flow - ONU1 UNI0 PON0, write metadata with cvid
+ // match outer vid 200, with inner cvid 60 -> modify outer vid to 100 and output on nni port
+ fa10 := &fu.FlowArgs{
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(536870912),
+ fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT | 200)),
+ fu.TunnelId(256),
+ },
+ Actions: []*ofp.OfpAction{
+ fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT | 100))),
+ fu.Output(2147483645),
+ },
+ KV: kwTable1Meter1WithCvid,
+ }
+
flow0, _ := fu.MkFlowStat(fa0)
flow1, _ := fu.MkFlowStat(fa1)
flow2, _ := fu.MkFlowStat(fa2)
@@ -1399,6 +1440,9 @@
flow7, _ := fu.MkFlowStat(fa7)
flow8, _ := fu.MkFlowStat(fa8)
+ flow9, _ := fu.MkFlowStat(fa9)
+ flow10, _ := fu.MkFlowStat(fa10)
+
type args struct {
ctx context.Context
intfID int32
@@ -1544,6 +1588,28 @@
},
wantErr: false,
},
+ {
+ name: "RouteFlowToOnuChannel-fttb-subscriber-downstream-12",
+ args: args{
+ ctx: ctx,
+ intfID: 0,
+ flow: flow9,
+ addFlow: true,
+ flowMetadata: &flowMetadata1,
+ },
+ wantErr: false,
+ },
+ {
+ name: "RouteFlowToOnuChannel-fttb-subscriber-upstream-13",
+ args: args{
+ ctx: ctx,
+ intfID: 0,
+ flow: flow10,
+ addFlow: true,
+ flowMetadata: &flowMetadata1,
+ },
+ wantErr: false,
+ },
}
var wg sync.WaitGroup