[VOL-3663] Supporting PPPoE trap rules olt adapter
Signed-off-by: Marcos Aurelio Carrero (Furukawa) <mcarrero@furukawalatam.com>
Change-Id: I0d96432493e25f3397f55730e04d35052aa148cf
diff --git a/internal/pkg/core/openolt_flowmgr.go b/internal/pkg/core/openolt_flowmgr.go
index 618a3f4..a9e2431 100644
--- a/internal/pkg/core/openolt_flowmgr.go
+++ b/internal/pkg/core/openolt_flowmgr.go
@@ -54,6 +54,8 @@
LldpEthType = 0x88cc
//IPv4EthType IPv4 ethernet type value
IPv4EthType = 0x800
+ //PPPoEDEthType PPPoE discovery ethernet type value
+ PPPoEDEthType = 0x8863
//ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
ReservedVlan = 4096
@@ -1274,11 +1276,11 @@
return nil
}
-// 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,
+// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
+func (f *OpenOltFlowMgr) addEthTypeBasedFlow(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, tpID uint32, pbitToGem map[uint32]uint32) error {
- logger.Infow(ctx, "adding-eapol-to-device",
+ gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32, ethType uint32) error {
+ logger.Infow(ctx, "adding-ethType-flow-to-device",
log.Fields{
"intf-id": intfID,
"onu-id": onuID,
@@ -1286,13 +1288,14 @@
"alloc-id": allocID,
"gemport-id": gemPortID,
"vlan-id": vlanID,
- "flow": logicalFlow})
+ "flow": logicalFlow,
+ "ethType": ethType})
uplinkClassifier := make(map[string]interface{})
uplinkAction := make(map[string]interface{})
// Fill Classfier
- uplinkClassifier[EthType] = uint32(EapEthType)
+ uplinkClassifier[EthType] = uint32(ethType)
uplinkClassifier[PacketTagType] = SingleTag
uplinkClassifier[VlanVid] = vlanID
uplinkClassifier[VlanPcp] = classifier[VlanPcp]
@@ -1302,11 +1305,12 @@
logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
"device-id": f.deviceHandler.device.Id,
"onu-id": onuID,
- "intf-id": intfID})
+ "intf-id": intfID,
+ "ethType": ethType})
return nil
}
- //Add Uplink EAPOL Flow
- logger.Debugw(ctx, "creating-ul-eapol-flow",
+ //Add Uplink EthType Flow
+ logger.Debugw(ctx, "creating-ul-ethType-flow",
log.Fields{
"ul_classifier": uplinkClassifier,
"ul_action": uplinkAction,
@@ -1362,11 +1366,12 @@
if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
}
- logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
+ logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
log.Fields{
"device-id": f.deviceHandler.device.Id,
"onu-id": onuID,
"intf-id": intfID,
+ "ethType": ethType,
})
flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(upstreamFlow.AccessIntfId), upstreamFlow.OnuId, upstreamFlow.UniId, upstreamFlow.FlowId, flowInfo); err != nil {
@@ -2253,13 +2258,19 @@
logger.Info(ctx, "adding-lldp-flow")
return f.addLLDPFlow(ctx, flow, portNo)
}
+ if ethType.(uint32) == PPPoEDEthType {
+ if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
+ logger.Debug(ctx, "trap-pppoed-from-nni-flow")
+ return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
+ }
+ }
}
if ipProto, ok := classifierInfo[IPProto]; ok {
if ipProto.(uint32) == IPProtoDhcp {
if udpSrc, ok := classifierInfo[UDPSrc]; ok {
if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
logger.Debug(ctx, "trap-dhcp-from-nni-flow")
- return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
+ return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
}
}
}
@@ -2604,15 +2615,15 @@
}
-func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
- logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
+func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
+ logger.Debug(ctx, "adding-trap-of-nni-flow")
action := make(map[string]interface{})
classifier[PacketTagType] = DoubleTag
action[TrapToHost] = true
/* We manage flowId resource pool on per PON port basis.
Since this situation is tricky, as a hack, we pass the NNI port
index (network_intf_id) as PON port Index for the flowId resource
- pool. Also, there is no ONU Id available for trapping DHCP packets
+ pool. Also, there is no ONU Id available for trapping packets
on NNI port, use onu_id as -1 (invalid)
****************** CAVEAT *******************
This logic works if the NNI Port Id falls within the same valid
@@ -2638,6 +2649,13 @@
return nil
}
+ logger.Debugw(ctx, "creating-trap-of-nni-flow",
+ log.Fields{
+ "classifier": classifier,
+ "action": action,
+ "flowId": logicalFlow.Id,
+ "intf-id": networkInterfaceID})
+
classifierProto, err := makeOpenOltClassifierField(classifier)
if err != nil {
return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
@@ -2664,7 +2682,7 @@
if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
}
- logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
+ logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
@@ -2847,11 +2865,12 @@
return
}
} else if ethType, ok := classifierInfo[EthType]; ok {
- if ethType.(uint32) == EapEthType {
- logger.Infow(ctx, "adding-eapol-flow", log.Fields{
+ if ethType.(uint32) == EapEthType || ethType.(uint32) == PPPoEDEthType {
+ logger.Infow(ctx, "adding-ethType-flow", log.Fields{
"intf-id": intfID,
"onu-id": onuID,
"uni-id": uniID,
+ "ethType": ethType,
})
var vlanID uint32
if val, ok := classifierInfo[VlanVid]; ok {
@@ -2859,7 +2878,7 @@
} else {
vlanID = DefaultMgmtVlan
}
- if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
+ if err := f.addEthTypeBasedFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem, ethType.(uint32)); err != nil {
logger.Warn(ctx, err)
}
}
diff --git a/internal/pkg/core/openolt_flowmgr_test.go b/internal/pkg/core/openolt_flowmgr_test.go
index 35c5d23..fad128a 100644
--- a/internal/pkg/core/openolt_flowmgr_test.go
+++ b/internal/pkg/core/openolt_flowmgr_test.go
@@ -305,6 +305,19 @@
multicastOfpStats, _ := fu.MkFlowStat(multicastFa)
multicastOfpStats.Id = 1
+ pppoedFa := &fu.FlowArgs{
+ KV: fu.OfpFlowModArgs{"priority": 1000, "cookie": 48132224281636694},
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(1),
+ fu.EthType(0x8863),
+ fu.TunnelId(536870912),
+ },
+ Actions: []*ofp.OfpAction{
+ fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
+ },
+ }
+ pppoedOfpStats, _ := fu.MkFlowStat(pppoedFa)
+
type args struct {
flow *ofp.OfpFlowStats
}
@@ -317,6 +330,7 @@
{"RemoveFlow", args{flow: lldpofpstats}},
{"RemoveFlow", args{flow: dhcpofpstats}},
{"RemoveFlow", args{flow: multicastOfpStats}},
+ {"RemoveFlow", args{flow: pppoedOfpStats}},
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
@@ -469,6 +483,19 @@
},
}
+ pppoedFa := &fu.FlowArgs{
+ KV: fu.OfpFlowModArgs{"priority": 1000, "cookie": 48132224281636694},
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(1),
+ fu.EthType(0x8863),
+ fu.TunnelId(536870912),
+ },
+ Actions: []*ofp.OfpAction{
+ fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 257)),
+ fu.Output(uint32(ofp.OfpPortNo_OFPP_CONTROLLER)),
+ },
+ }
+
fa9 := &fu.FlowArgs{
MatchFields: []*ofp.OfpOxmOfbField{
fu.InPort(536870912),
@@ -534,6 +561,7 @@
ofpstats10, _ := fu.MkFlowStat(fa10)
igmpstats, _ := fu.MkFlowStat(igmpFa)
ofpstats11, _ := fu.MkFlowStat(fa11)
+ pppoedstats, _ := fu.MkFlowStat(pppoedFa)
fmt.Println(ofpstats6, ofpstats9, ofpstats10)
@@ -563,6 +591,7 @@
//{"AddFlow", args{flow: ofpstats10, flowMetadata: flowMetadata}},
//ofpstats10
{"AddFlow", args{flow: ofpstats11, flowMetadata: flowMetadata}},
+ {"AddFlow", args{flow: pppoedstats, flowMetadata: flowMetadata}},
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
@@ -919,6 +948,23 @@
KV: kw,
}
+ // PPPOED
+ pppoedFA := &fu.FlowArgs{
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(536870912),
+ fu.Metadata_ofp(1),
+ fu.EthType(0x8863),
+ fu.VlanPcp(1),
+ fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 257),
+ },
+ Actions: []*ofp.OfpAction{
+ fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 257)),
+ fu.Output(1048576),
+ fu.PushVlan(0x8100),
+ },
+ KV: kw,
+ }
+
classifierInfo := make(map[string]interface{})
actionInfo := make(map[string]interface{})
classifierInfo2 := make(map[string]interface{})
@@ -927,14 +973,18 @@
actionInfo3 := make(map[string]interface{})
classifierInfo4 := make(map[string]interface{})
actionInfo4 := make(map[string]interface{})
+ classifierInfo5 := make(map[string]interface{})
+ actionInfo5 := make(map[string]interface{})
flow, _ := fu.MkFlowStat(fa)
flow2, _ := fu.MkFlowStat(fa2)
flow3, _ := fu.MkFlowStat(fa3)
flow4, _ := fu.MkFlowStat(fa4)
+ flow5, _ := fu.MkFlowStat(pppoedFA)
formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
formulateClassifierInfoFromFlow(ctx, classifierInfo2, flow2)
formulateClassifierInfoFromFlow(ctx, classifierInfo3, flow3)
formulateClassifierInfoFromFlow(ctx, classifierInfo4, flow4)
+ formulateClassifierInfoFromFlow(ctx, classifierInfo5, flow5)
err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
if err != nil {
@@ -964,6 +1014,13 @@
return
}
+ err = formulateActionInfoFromFlow(ctx, actionInfo5, classifierInfo5, flow5)
+ if err != nil {
+ // Error logging is already done in the called function
+ // So just return in case of error
+ return
+ }
+
TpInst := &tp.TechProfile{
Name: "Test-Tech-Profile",
SubscriberIdentifier: "257",
@@ -1105,6 +1162,25 @@
uni: "16",
},
},
+ {
+ name: "checkAndAddFlow-5",
+ args: args{
+ args: nil,
+ classifierInfo: classifierInfo5,
+ actionInfo: actionInfo5,
+ flow: flow5,
+ gemPort: 1,
+ intfID: 1,
+ onuID: 1,
+ uniID: 16,
+ portNo: 1,
+ TpInst: TpInst,
+ allocID: []uint32{0x8001},
+ gemPorts: []uint32{1, 2, 3, 4},
+ TpID: 64,
+ uni: "16",
+ },
+ },
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
@@ -1313,6 +1389,7 @@
},
KV: kwTable1Meter1,
}
+
// Upstream EAPOL - ONU1 UNI0 PON15
fa6 := &fu.FlowArgs{
MatchFields: []*ofp.OfpOxmOfbField{
@@ -1331,6 +1408,44 @@
},
KV: kwTable1Meter1,
}
+
+ // Upstream PPPOED - ONU1 UNI0 PON0
+ fa7 := &fu.FlowArgs{
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(536870912),
+ fu.Metadata_ofp(1),
+ fu.EthType(0x8863),
+ fu.VlanPcp(1),
+ fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 257),
+ fu.TunnelId(16),
+ },
+ Actions: []*ofp.OfpAction{
+ //fu.SetField(fu.Metadata_ofp(uint64(ofp.OfpInstructionType_OFPIT_WRITE_METADATA | 2))),
+ fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 257)),
+ fu.Output(2147483645),
+ fu.PushVlan(0x8100),
+ },
+ KV: kwTable1Meter1,
+ }
+
+ // Upstream PPPOED - ONU1 UNI0 PON15
+ fa8 := &fu.FlowArgs{
+ MatchFields: []*ofp.OfpOxmOfbField{
+ fu.InPort(536870927),
+ fu.Metadata_ofp(1),
+ fu.EthType(0x8863),
+ fu.VlanPcp(1),
+ fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 259),
+ fu.TunnelId(16),
+ },
+ Actions: []*ofp.OfpAction{
+ //fu.SetField(fu.Metadata_ofp(uint64(ofp.OfpInstructionType_OFPIT_WRITE_METADATA | 2))),
+ fu.SetField(fu.VlanVid(uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 257)),
+ fu.Output(2147483645),
+ fu.PushVlan(0x8100),
+ },
+ KV: kwTable1Meter1,
+ }
flow0, _ := fu.MkFlowStat(fa0)
flow1, _ := fu.MkFlowStat(fa1)
flow2, _ := fu.MkFlowStat(fa2)
@@ -1339,6 +1454,8 @@
flow5, _ := fu.MkFlowStat(fa5)
flow6, _ := fu.MkFlowStat(fa6)
+ flow7, _ := fu.MkFlowStat(fa7)
+ flow8, _ := fu.MkFlowStat(fa8)
type args struct {
ctx context.Context
@@ -1442,6 +1559,26 @@
},
wantErr: false,
},
+ {
+ name: "RouteFlowToOnuChannel-9",
+ args: args{
+ ctx: ctx,
+ flow: flow7,
+ addFlow: true,
+ flowMetadata: &flowMetadata1,
+ },
+ wantErr: false,
+ },
+ {
+ name: "RouteFlowToOnuChannel-10",
+ args: args{
+ ctx: ctx,
+ flow: flow8,
+ addFlow: true,
+ flowMetadata: &flowMetadata1,
+ },
+ wantErr: false,
+ },
}
var wg sync.WaitGroup