WIP - Suggesting changes (take2)
This is not yet completed, still working on things. Eventually the plan
is to provide the following changes
- restructure repo to be more aligned with https://github.com/golang-standards/project-layout
- add k8s probes
- modifications (golang range loops, etc) to follow some golang
practices
Change-Id: I6922cbc00b5ef17ceab183aba00a7fc59ab46480
diff --git a/internal/pkg/openflow/flowMod.go b/internal/pkg/openflow/flowMod.go
new file mode 100644
index 0000000..42f37f2
--- /dev/null
+++ b/internal/pkg/openflow/flowMod.go
@@ -0,0 +1,346 @@
+/*
+ Copyright 2020 the original author or authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package openflow
+
+import (
+ "context"
+ "encoding/json"
+ ofp "github.com/donNewtonAlpha/goloxi/of13"
+ "github.com/opencord/voltha-lib-go/v2/pkg/log"
+ "github.com/opencord/voltha-protos/v2/go/openflow_13"
+ "github.com/opencord/voltha-protos/v2/go/voltha"
+)
+
+var oxmMap = map[string]int32{
+ "in_port": 0,
+ "in_phy_port": 1,
+ "metadata": 2,
+ "eth_dst": 3,
+ "eth_src": 4,
+ "eth_type": 5,
+ "vlan_vid": 6,
+ "vlan_pcp": 7,
+ "ip_dscp": 8,
+ "ip_ecn": 9,
+ "ip_proto": 10,
+ "ipv4_src": 11,
+ "ipv4_dst": 12,
+ "tcp_src": 13,
+ "tcp_dst": 14,
+ "udp_src": 15,
+ "udp_dst": 16,
+ "sctp_src": 17,
+ "sctp_dst": 18,
+ "icmpv4_type": 19,
+ "icmpv4_code": 20,
+ "arp_op": 21,
+ "arp_spa": 22,
+ "arp_tpa": 23,
+ "arp_sha": 24,
+ "arp_tha": 25,
+ "ipv6_src": 26,
+ "ipv6_dst": 27,
+ "ipv6_flabel": 28,
+ "icmpv6_type": 29,
+ "icmpv6_code": 30,
+ "ipv6_nd_target": 31,
+ "ipv6_nd_sll": 32,
+ "ipv6_nd_tll": 33,
+ "mpls_label": 34,
+ "mpls_tc": 35,
+ "mpls_bos": 36,
+ "pbb_isid": 37,
+ "tunnel_id": 38,
+ "ipv6_exthdr": 39,
+}
+
+func (ofc *OFClient) handleFlowAdd(flowAdd *ofp.FlowAdd) {
+ if logger.V(log.DebugLevel) {
+ js, _ := json.Marshal(flowAdd)
+ logger.Debugw("handleFlowAdd called",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "params": js})
+ }
+
+ // Construct the match
+ var oxmList []*voltha.OfpOxmField
+ for _, oxmField := range flowAdd.Match.GetOxmList() {
+ name := oxmMap[oxmField.GetOXMName()]
+ val := oxmField.GetOXMValue()
+ field := voltha.OfpOxmOfbField{Type: voltha.OxmOfbFieldTypes(name)}
+ ofpOxmField := voltha.OfpOxmField{
+ OxmClass: ofp.OFPXMCOpenflowBasic,
+ Field: &openflow_13.OfpOxmField_OfbField{OfbField: &field},
+ }
+ switch voltha.OxmOfbFieldTypes(name) {
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
+ field.Value = &voltha.OfpOxmOfbField_Port{
+ Port: uint32(val.(ofp.Port)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
+ field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
+ PhysicalPort: val.(uint32),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
+ field.Value = &voltha.OfpOxmOfbField_TableMetadata{
+ TableMetadata: val.(uint64),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
+ field.Value = &voltha.OfpOxmOfbField_EthType{
+ EthType: uint32(val.(ofp.EthernetType)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
+ field.Value = &voltha.OfpOxmOfbField_IpProto{
+ IpProto: uint32(val.(ofp.IpPrototype)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
+ field.Value = &voltha.OfpOxmOfbField_UdpSrc{
+ UdpSrc: uint32(val.(uint16)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
+ field.Value = &voltha.OfpOxmOfbField_UdpDst{
+ UdpDst: uint32(val.(uint16)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
+ field.Value = &voltha.OfpOxmOfbField_VlanVid{
+ VlanVid: uint32((val.(uint16) & 0xfff) | 0x1000),
+ }
+ }
+ oxmList = append(oxmList, &ofpOxmField)
+ }
+
+ // Construct the instructions
+ var instructions []*voltha.OfpInstruction
+ for _, ofpInstruction := range flowAdd.GetInstructions() {
+ instructionType := ofpInstruction.GetType()
+ instruction := voltha.OfpInstruction{Type: uint32(instructionType)}
+ switch instructionType {
+ case ofp.OFPITGotoTable:
+ instruction.Data = &openflow_13.OfpInstruction_GotoTable{
+ GotoTable: &openflow_13.OfpInstructionGotoTable{
+ TableId: uint32(ofpInstruction.(ofp.IInstructionGotoTable).GetTableId()),
+ },
+ }
+ case ofp.OFPITWriteMetadata:
+ instruction.Data = &openflow_13.OfpInstruction_WriteMetadata{
+ WriteMetadata: &openflow_13.OfpInstructionWriteMetadata{
+ Metadata: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadata(),
+ MetadataMask: ofpInstruction.(ofp.IInstructionWriteMetadata).GetMetadataMask(),
+ },
+ }
+ case ofp.OFPITWriteActions:
+ var ofpActions []*openflow_13.OfpAction
+ for _, action := range ofpInstruction.(ofp.IInstructionWriteActions).GetActions() {
+ ofpActions = append(ofpActions, extractAction(action))
+ }
+ instruction.Data = &openflow_13.OfpInstruction_Actions{
+ Actions: &openflow_13.OfpInstructionActions{
+ Actions: ofpActions,
+ },
+ }
+ case ofp.OFPITApplyActions:
+ var ofpActions []*openflow_13.OfpAction
+ for _, action := range ofpInstruction.(ofp.IInstructionApplyActions).GetActions() {
+ ofpActions = append(ofpActions, extractAction(action))
+ }
+ instruction.Data = &openflow_13.OfpInstruction_Actions{
+ Actions: &openflow_13.OfpInstructionActions{
+ Actions: ofpActions,
+ },
+ }
+ case ofp.OFPITMeter:
+ instruction.Data = &openflow_13.OfpInstruction_Meter{
+ Meter: &openflow_13.OfpInstructionMeter{
+ MeterId: ofpInstruction.(ofp.IInstructionMeter).GetMeterId(),
+ },
+ }
+ }
+ instructions = append(instructions, &instruction)
+ }
+
+ // Construct the request
+ flowUpdate := openflow_13.FlowTableUpdate{
+ Id: ofc.DeviceID,
+ FlowMod: &voltha.OfpFlowMod{
+ Cookie: flowAdd.Cookie,
+ CookieMask: flowAdd.CookieMask,
+ TableId: uint32(flowAdd.TableId),
+ Command: voltha.OfpFlowModCommand_OFPFC_ADD,
+ IdleTimeout: uint32(flowAdd.IdleTimeout),
+ HardTimeout: uint32(flowAdd.HardTimeout),
+ Priority: uint32(flowAdd.Priority),
+ BufferId: flowAdd.BufferId,
+ OutPort: uint32(flowAdd.OutPort),
+ OutGroup: uint32(flowAdd.OutGroup),
+ Flags: uint32(flowAdd.Flags),
+ Match: &voltha.OfpMatch{
+ Type: voltha.OfpMatchType(flowAdd.Match.GetType()),
+ OxmFields: oxmList,
+ },
+
+ Instructions: instructions,
+ },
+ }
+ if logger.V(log.DebugLevel) {
+ flowUpdateJs, _ := json.Marshal(flowUpdate)
+ logger.Debugf("FlowUpdate being sent to Voltha",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "flow-mod-request": flowUpdateJs})
+ }
+ if _, err := ofc.VolthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
+ logger.Errorw("Error calling FlowUpdate ",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "error": err})
+ }
+}
+
+func (ofc *OFClient) handleFlowMod(flowMod *ofp.FlowMod) {
+ if logger.V(log.DebugLevel) {
+ js, _ := json.Marshal(flowMod)
+ logger.Debugw("handleMod called",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "flow-mod": js})
+ }
+ logger.Errorw("handleFlowMod not implemented",
+ log.Fields{"device-id": ofc.DeviceID})
+}
+
+func (ofc *OFClient) handleFlowModStrict(flowModStrict *ofp.FlowModifyStrict) {
+ if logger.V(log.DebugLevel) {
+ js, _ := json.Marshal(flowModStrict)
+ logger.Debugw("handleFlowModStrict called",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "flow-mod-strict": js})
+ }
+ logger.Error("handleFlowModStrict not implemented",
+ log.Fields{"device-id": ofc.DeviceID})
+}
+
+func (ofc *OFClient) handleFlowDelete(flowDelete *ofp.FlowDelete) {
+ if logger.V(log.DebugLevel) {
+ js, _ := json.Marshal(flowDelete)
+ logger.Debugw("handleFlowDelete called",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "flow-delete": js})
+ }
+ logger.Error("handleFlowDelete not implemented",
+ log.Fields{"device-id": ofc.DeviceID})
+
+}
+
+func (ofc *OFClient) handleFlowDeleteStrict(flowDeleteStrict *ofp.FlowDeleteStrict) {
+ if logger.V(log.DebugLevel) {
+ js, _ := json.Marshal(flowDeleteStrict)
+ logger.Debugw("handleFlowAdd called",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "flow-delete-strict": js})
+ }
+
+ // Construct match
+ var oxmList []*voltha.OfpOxmField
+ for _, oxmField := range flowDeleteStrict.Match.GetOxmList() {
+ name := oxmMap[oxmField.GetOXMName()]
+ val := oxmField.GetOXMValue()
+ var ofpOxmField voltha.OfpOxmField
+ ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
+ var field voltha.OfpOxmOfbField
+ field.Type = voltha.OxmOfbFieldTypes(name)
+
+ var x openflow_13.OfpOxmField_OfbField
+ x.OfbField = &field
+ ofpOxmField.Field = &x
+
+ switch voltha.OxmOfbFieldTypes(name) {
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
+ field.Value = &voltha.OfpOxmOfbField_Port{
+ Port: uint32(val.(ofp.Port)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
+ field.Value = &voltha.OfpOxmOfbField_PhysicalPort{
+ PhysicalPort: val.(uint32),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
+ field.Value = &voltha.OfpOxmOfbField_TableMetadata{
+ TableMetadata: val.(uint64),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
+ field.Value = &voltha.OfpOxmOfbField_EthType{
+ EthType: uint32(val.(ofp.EthernetType)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
+ field.Value = &voltha.OfpOxmOfbField_IpProto{
+ IpProto: uint32(val.(ofp.IpPrototype)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
+ field.Value = &voltha.OfpOxmOfbField_UdpSrc{
+ UdpSrc: uint32(val.(uint16)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
+ field.Value = &voltha.OfpOxmOfbField_UdpDst{
+ UdpDst: uint32(val.(uint16)),
+ }
+ case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
+ field.Value = &voltha.OfpOxmOfbField_VlanVid{
+ VlanVid: uint32(val.(uint16)),
+ }
+ }
+ oxmList = append(oxmList, &ofpOxmField)
+ }
+
+ // Construct request
+ flowUpdate := openflow_13.FlowTableUpdate{
+ Id: ofc.DeviceID,
+ FlowMod: &voltha.OfpFlowMod{
+ Cookie: flowDeleteStrict.Cookie,
+ CookieMask: flowDeleteStrict.CookieMask,
+ TableId: uint32(flowDeleteStrict.TableId),
+ Command: voltha.OfpFlowModCommand_OFPFC_DELETE_STRICT,
+ IdleTimeout: uint32(flowDeleteStrict.IdleTimeout),
+ HardTimeout: uint32(flowDeleteStrict.HardTimeout),
+ Priority: uint32(flowDeleteStrict.Priority),
+ BufferId: flowDeleteStrict.BufferId,
+ OutPort: uint32(flowDeleteStrict.OutPort),
+ OutGroup: uint32(flowDeleteStrict.OutGroup),
+ Flags: uint32(flowDeleteStrict.Flags),
+ Match: &voltha.OfpMatch{
+ Type: voltha.OfpMatchType(flowDeleteStrict.Match.GetType()),
+ OxmFields: oxmList,
+ },
+ },
+ }
+
+ if logger.V(log.DebugLevel) {
+ flowUpdateJs, _ := json.Marshal(flowUpdate)
+ logger.Debugf("FlowUpdate being sent to Voltha",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "flow-update": flowUpdateJs})
+ }
+ if _, err := ofc.VolthaClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate); err != nil {
+ logger.Errorw("Error calling FlowUpdate ",
+ log.Fields{
+ "device-id": ofc.DeviceID,
+ "error": err})
+ }
+}