blob: 37e68646bc640e4721255ed9774fd5aeee8d5774 [file] [log] [blame]
/*
Copyright 2017 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"
"github.com/opencord/voltha-protos/go/openflow_13"
pb "github.com/opencord/voltha-protos/go/voltha"
ofp "github.com/skydive-project/goloxi/of13"
"log"
)
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 handleFlowAdd(flowAdd *ofp.FlowAdd, deviceId string) {
js, _ := json.Marshal(flowAdd)
log.Printf("handleFlowAdd called with %s", js)
var flowUpdate openflow_13.FlowTableUpdate
flowUpdate.Id = deviceId
var flowMod pb.OfpFlowMod
flowMod.Cookie = flowAdd.Cookie
flowMod.CookieMask = flowAdd.CookieMask
flowMod.TableId = uint32(flowAdd.TableId)
flowMod.Command = pb.OfpFlowModCommand_OFPFC_ADD
flowMod.IdleTimeout = uint32(flowAdd.IdleTimeout)
flowMod.HardTimeout = uint32(flowAdd.HardTimeout)
flowMod.Priority = uint32(flowAdd.Priority)
flowMod.BufferId = flowAdd.BufferId
flowMod.OutPort = uint32(flowAdd.OutPort)
flowMod.OutGroup = uint32(flowAdd.OutGroup)
flowMod.Flags = uint32(flowAdd.Flags)
inMatch := flowAdd.Match
var flowMatch pb.OfpMatch
flowMatch.Type = pb.OfpMatchType(inMatch.GetType())
var oxmList []*pb.OfpOxmField
inOxmList := inMatch.GetOxmList()
for i := 0; i < len(inOxmList); i++ {
oxmField := inOxmList[i]
j, _ := json.Marshal(oxmField)
name := oxmMap[oxmField.GetOXMName()]
log.Printf("\n\n\n %s %d %s\n\n\n", j, name, oxmField.GetOXMName())
val := oxmField.GetOXMValue()
var ofpOxmField pb.OfpOxmField
ofpOxmField.OxmClass = ofp.OFPXMCOpenflowBasic
var field pb.OfpOxmOfbField
field.Type = pb.OxmOfbFieldTypes(name)
log.Println("****\nFieldType: " + openflow_13.OxmOfbFieldTypes_name[name] + "\n\n\n\n")
var x openflow_13.OfpOxmField_OfbField
x.OfbField = &field
ofpOxmField.Field = &x
switch pb.OxmOfbFieldTypes(name) {
case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
port := val.(ofp.Port)
var value pb.OfpOxmOfbField_Port
value.Port = uint32(port)
field.Value = &value
case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
phyPort := val.(uint32)
var value pb.OfpOxmOfbField_PhysicalPort
value.PhysicalPort = phyPort
field.Value = &value
case pb.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
metadata := val.(uint64)
var value pb.OfpOxmOfbField_TableMetadata
value.TableMetadata = metadata
field.Value = &value
case pb.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
ethType := val.(ofp.EthernetType)
var value pb.OfpOxmOfbField_EthType
value.EthType = uint32(ethType)
field.Value = &value
case pb.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
proto := val.(ofp.IpPrototype)
var value pb.OfpOxmOfbField_IpProto
value.IpProto = uint32(proto)
field.Value = &value
case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
udpSrc := val.(uint16)
var value pb.OfpOxmOfbField_UdpSrc
value.UdpSrc = uint32(udpSrc)
log.Printf("udpSrc %v", udpSrc)
field.Value = &value
case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
udpDst := val.(uint16)
var value pb.OfpOxmOfbField_UdpDst
value.UdpDst = uint32(udpDst)
field.Value = &value
}
oxmList = append(oxmList, &ofpOxmField)
}
flowMatch.OxmFields = oxmList
flowMod.Match = &flowMatch
var instructions []*pb.OfpInstruction
ofpInstructions := flowAdd.GetInstructions()
for i := 0; i < len(ofpInstructions); i++ {
var instruction pb.OfpInstruction
ofpInstruction := ofpInstructions[i]
instructionType := ofpInstruction.GetType()
instruction.Type = uint32(instructionType)
switch instructionType {
case 1:
goToTable := ofpInstruction.(ofp.IInstructionGotoTable)
var ofpGoToTable openflow_13.OfpInstruction_GotoTable
ofpGoToTable.GotoTable.TableId = uint32(goToTable.GetTableId())
instruction.Data = &ofpGoToTable
case 2:
writeMetaData := ofpInstruction.(ofp.IInstructionWriteMetadata)
var ofpWriteMetadata openflow_13.OfpInstruction_WriteMetadata
ofpWriteMetadata.WriteMetadata.Metadata = writeMetaData.GetMetadata()
ofpWriteMetadata.WriteMetadata.MetadataMask = writeMetaData.GetMetadataMask()
instruction.Data = &ofpWriteMetadata
case 3:
writeAction := ofpInstruction.(ofp.IInstructionWriteActions)
var ofpInstructionActions openflow_13.OfpInstruction_Actions
var ofpActions []*openflow_13.OfpAction
actions := writeAction.GetActions()
for i := 0; i < len(actions); i++ {
action := actions[i]
ofpAction := extractAction(action)
ofpActions = append(ofpActions, ofpAction)
}
instruction.Data = &ofpInstructionActions
case 4:
applyAction := ofpInstruction.(ofp.IInstructionApplyActions)
var ofpInstructionActions openflow_13.OfpInstruction_Actions
var ofpActions []*openflow_13.OfpAction
actions := applyAction.GetActions()
for i := 0; i < len(actions); i++ {
action := actions[i]
ofpAction := extractAction(action)
ofpActions = append(ofpActions, ofpAction)
}
var actionsHolder openflow_13.OfpInstructionActions
actionsHolder.Actions = ofpActions
ofpInstructionActions.Actions = &actionsHolder
instruction.Data = &ofpInstructionActions
}
instructions = append(instructions, &instruction)
}
flowMod.Instructions = instructions
flowUpdate.FlowMod = &flowMod
grpcClient := *getGrpcClient()
flowUpdateJs, _ := json.Marshal(flowUpdate)
log.Printf("FLOW UPDATE %s", flowUpdateJs)
empty, err := grpcClient.UpdateLogicalDeviceFlowTable(context.Background(), &flowUpdate)
if err != nil {
log.Printf("ERROR DOING FLOW MOD ADD %v", err)
}
emptyJs, _ := json.Marshal(empty)
log.Printf("FLOW MOD RESPONSE %s", emptyJs)
}
func handleFlowMod(flowMod *ofp.FlowMod, deviceId string) {
js, _ := json.Marshal(flowMod)
log.Printf("handleFlowMod called with %s", js)
}
func handleFlowModStrict(flowModStrict *ofp.FlowModifyStrict, deviceId string) {
js, _ := json.Marshal(flowModStrict)
log.Printf("handleFlowModStrict called with %s", js)
}
func handleFlowDelete(flowDelete *ofp.FlowDelete, deviceId string) {
js, _ := json.Marshal(flowDelete)
log.Printf("handleFlowDelete called with %s", js)
}
func handleFlowDeleteStrict(flowDeleteStrict *ofp.FlowDeleteStrict, deviceId string) {
js, _ := json.Marshal(flowDeleteStrict)
log.Printf("handleFlowDeleteStrict called with %s", js)
}
func extractAction(action ofp.IAction) *openflow_13.OfpAction {
var ofpAction openflow_13.OfpAction
switch action.GetType() {
case 0: // Output
var outputAction openflow_13.OfpAction_Output
loxiOutputAction := action.(*ofp.ActionOutput)
var output openflow_13.OfpActionOutput
output.Port = uint32(loxiOutputAction.Port)
output.MaxLen = uint32(loxiOutputAction.MaxLen)
outputAction.Output = &output
ofpAction.Action = &outputAction
case 11: //CopyTtlOut
case 12: //CopyTtlIn
case 15: //SetMplsTtl
case 16: //DecMplsTtl
case 17: //PushVlan
var pushVlan openflow_13.OfpAction_Push
loxiPushAction := action.(*ofp.ActionPopVlan)
fields := loxiPushAction.GetActionFields()
fieldsJS, _ := json.Marshal(fields)
log.Printf("\n\nPushVlan fields %s\n\n", fieldsJS)
pushVlan.Push.Ethertype = 0x8100 //TODO This should be available in the fields
ofpAction.Type = openflow_13.OfpActionType_OFPAT_PUSH_VLAN
case 18: //PopVlan
ofpAction.Type = openflow_13.OfpActionType_OFPAT_POP_VLAN
case 19: //PushMpls
case 20: //PopMpls
case 21: //SetQueue
case 22: //ActionGroup
case 23: //SetNwTtl
case 24: //DecNwTtl
case 25: //SetField
var setField openflow_13.OfpAction_SetField
loxiSetField := action.(*ofp.ActionSetField)
fields := loxiSetField.GetActionFields()
fieldsJS, _ := json.Marshal(fields)
log.Printf("\n\nSet Fields fields %s\n\n", fieldsJS)
ofpAction.Action = &setField
case 26: //PushPbb
case 27: //PopPbb
case 65535: //Experimenter
}
return &ofpAction
}