/*
 * Copyright 2017-present Open Networking Foundation

 * 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 core

import (
	"context"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"github.com/opencord/voltha/ponsim/v2/common"
	"github.com/opencord/voltha/protos/go/openflow_13"
	"github.com/sirupsen/logrus"
	"net"
	"sort"
)

// TODO: Pass-in the certificate information as a structure parameter
// TODO: Add certification information

type PonSimDevice struct {
	Name        string               `json:name`
	Port        int32                `json:port`
	Address     string               `json:address`
	ExternalIf  string               `json:external_if`
	InternalIf  string               `json:internal_if`
	Promiscuous bool                 `json:promiscuous`
	SnapshotLen int32                `json:snapshot_len`
	AlarmsOn    bool                 `json:alarm_on`
	AlarmsFreq  int                  `json:alarm_freq`
	Counter     *PonSimMetricCounter `json:counter`

	//*grpc.GrpcSecurity

	flows          []*openflow_13.OfpFlowStats `json:-`
	ingressHandler *pcap.Handle                `json:-`
	egressHandler  *pcap.Handle                `json:-`
	links          map[int]map[int]interface{} `json:-`
}

const (
	UDP_DST  = 1
	UDP_SRC  = 2
	IPV4_DST = 4
	VLAN_PCP = 8
	VLAN_VID = 16
	IP_PROTO = 32
	ETH_TYPE = 64
	IN_PORT  = 128
)

/*
Start performs common setup operations for a ponsim device
*/
func (o *PonSimDevice) Start(ctx context.Context) {
}

/*
Stop performs common cleanup operations for a ponsim device
*/
func (o *PonSimDevice) Stop(ctx context.Context) {
}

/*
GetAddress returns the IP/FQDN for the device
*/
func (o *PonSimDevice) GetAddress() string {
	return o.Address
}

/*
GetPort return the port assigned to the device
*/
func (o *PonSimDevice) GetPort() int32 {
	return o.Port
}

/*
Forward is responsible of processing incoming data, filtering it and redirecting to the
intended destination
*/
func (o *PonSimDevice) Forward(
	ctx context.Context,
	port int,
	frame gopacket.Packet,
) error {
	common.Logger().WithFields(logrus.Fields{
		"device": o,
		"port":   port,
		"frame":  frame,
	}).Debug("Forwarding packet")

	var err error

	o.Counter.CountRxFrame(port, len(common.GetEthernetLayer(frame).Payload))

	if egressPort, egressFrame := o.processFrame(ctx, port, frame); egressFrame != nil {
		forwarded := 0
		links := o.links[int(egressPort)]

		o.Counter.CountTxFrame(int(egressPort), len(common.GetEthernetLayer(egressFrame).Payload))

		for _, link := range links {
			forwarded += 1

			common.Logger().WithFields(logrus.Fields{
				"device":      o,
				"egressPort":  port,
				"egressFrame": egressFrame,
			}).Debug("Forwarding packet to link")

			link.(func(int, gopacket.Packet))(int(egressPort), egressFrame)
		}
		if forwarded == 0 {
			common.Logger().WithFields(logrus.Fields{
				"device": o,
				"port":   port,
				"frame":  frame,
			}).Warn("Nothing was forwarded")
		}
	} else {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"port":   egressPort,
			"frame":  egressFrame,
		}).Error("Failed to properly process frame")
	}

	return err
}

/*
connectNetworkInterfaces opens network interfaces for reading and/or writing packets
*/
func (o *PonSimDevice) connectNetworkInterfaces() {
	common.Logger().WithFields(logrus.Fields{
		"device": o,
	}).Debug("Opening network interfaces")

	var err error
	if o.ingressHandler, err = pcap.OpenLive(
		o.ExternalIf, o.SnapshotLen, o.Promiscuous, pcap.BlockForever,
	); err != nil {
		common.Logger().WithFields(logrus.Fields{
			"device":    o,
			"interface": o.ExternalIf,
			"error":     err.Error(),
		}).Fatal("Unable to open Ingress interface")
	} else {
		common.Logger().WithFields(logrus.Fields{
			"device":    o,
			"interface": o.ExternalIf,
		}).Info("Opened Ingress interface")
	}

	if o.egressHandler, err = pcap.OpenLive(
		o.InternalIf, o.SnapshotLen, o.Promiscuous, pcap.BlockForever,
	); err != nil {
		common.Logger().WithFields(logrus.Fields{
			"device":    o,
			"interface": o.InternalIf,
			"error":     err.Error(),
		}).Fatal("Unable to open egress interface")
	} else {
		common.Logger().WithFields(logrus.Fields{
			"device":    o,
			"interface": o.InternalIf,
		}).Info("Opened egress interface")
	}
}

/*
AddLink assigns a functional operation to a device endpoint

The functional operation is called whenever a packet has been processed
and the endpoint has been identified as the outgoing interface
*/
func (o *PonSimDevice) AddLink(
	port int,
	index int,
	function interface{},
) error {
	common.Logger().WithFields(logrus.Fields{
		"device": o,
		"port":   port,
		"index":  index,
	}).Debug("Linking port to functional operation")

	if o.links == nil {
		o.links = make(map[int]map[int]interface{})
	}
	if _, ok := o.links[port]; !ok {
		o.links[port] = make(map[int]interface{})
	}
	o.links[port][index] = function

	return nil
}

/*
RemoveLink will remove reference a functional operation for a given port and index
*/
func (o *PonSimDevice) RemoveLink(
	port int,
	index int,
) error {
	if _, hasPort := o.links[port]; hasPort {
		if _, hasIndex := o.links[port][index]; hasIndex {
			common.Logger().WithFields(logrus.Fields{
				"device": o,
				"port":   port,
				"index":  index,
			}).Debug("Removing link functional operation")

			delete(o.links[port], index)

		} else {
			common.Logger().WithFields(logrus.Fields{
				"device": o,
				"port":   port,
				"index":  index,
			}).Warn("No such index for link functional operation")

		}
	} else {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"port":   port,
			"index":  index,
		}).Warn("No such port for functional operation")
	}

	return nil
}

/*
InstallFlows assigns flows to the device in order of priority
*/
func (o *PonSimDevice) InstallFlows(
	ctx context.Context,
	flows []*openflow_13.OfpFlowStats,
) error {
	common.Logger().WithFields(logrus.Fields{
		"device": o,
		"flows":  flows,
	}).Debug("Installing flows")

	o.flows = flows
	sort.Sort(common.SortByPriority(o.flows))

	common.Logger().WithFields(logrus.Fields{
		"device": o,
	}).Debug("Installed sorted flows")

	return nil
}

/*
processFrame is responsible for matching or discarding a frame based on the configured flows
*/
func (o *PonSimDevice) processFrame(
	ctx context.Context,
	port int,
	frame gopacket.Packet,
) (uint32, gopacket.Packet) {
	common.Logger().WithFields(logrus.Fields{
		"device": o,
		"port":   port,
		"frame":  frame,
	}).Debug("Processing frame")

	var err error
	var matchedMask int = 0
	var currentMask int
	var highestPriority uint32 = 0
	var matchedFlow *openflow_13.OfpFlowStats = nil

	common.Logger().WithFields(logrus.Fields{
		"device": o,
	}).Debug("Looping through flows")

	for _, flow := range o.flows {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"flow":   flow,
		}).Debug("Checking flow")

		if matchedFlow != nil && flow.Priority < highestPriority {
			common.Logger().WithFields(logrus.Fields{
				"device":      o,
				"matchedFlow": matchedFlow,
				"priority":    highestPriority,
			}).Debug("Flow has already been matched")
			break
		} else {
			common.Logger().WithFields(logrus.Fields{
				"device":          o,
				"matchedFlow":     matchedFlow,
				"priority":        flow.Priority,
				"highestPriority": highestPriority,
			}).Debug("Flow OR Priority requirements not met")
		}

		highestPriority = flow.Priority
		if currentMask, err = o.isMatch(ctx, flow, port, frame); err != nil {
			common.Logger().WithFields(logrus.Fields{
				"device": o,
				"flow":   flow,
				"port":   port,
				"frame":  frame,
				"error":  err.Error(),
			}).Error("Problem while matching flow")

		} else if currentMask > matchedMask {
			matchedMask = currentMask
			matchedFlow = flow

			common.Logger().WithFields(logrus.Fields{
				"device":      o,
				"matchedFlow": flow,
				"port":        port,
				"frame":       frame,
				"matchedMask": matchedMask,
			}).Debug("Flow matches")
		}
	}

	if matchedFlow != nil {
		egressPort, egressFrame := o.processActions(ctx, matchedFlow, frame)

		common.Logger().WithFields(logrus.Fields{
			"device":      o,
			"port":        port,
			"egressPort":  egressPort,
			"egressFrame": egressFrame,
		}).Debug("Processed actions to matched flow")

		return egressPort, egressFrame
	} else {
		common.Logger().WithFields(logrus.Fields{
			"device":      o,
			"port":        port,
			"frame":       frame,
			"matchedMask": matchedMask,
		}).Warn("Flow was not successfully matched")
	}

	return 0, nil
}

/*
isMatch traverses the criteria of a flow and identify all matching elements of a frame (if any)
*/
func (o *PonSimDevice) isMatch(
	ctx context.Context,
	flow *openflow_13.OfpFlowStats,
	port int,
	frame gopacket.Packet,
) (int, error) {
	matchedMask := 0

	for _, ofbfield := range flow.Match.OxmFields {
		if ofbfield.GetOxmClass() == openflow_13.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
			switch ofbfield.GetOfbField().Type {
			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
				if ofbfield.GetOfbField().GetPort() != uint32(port) {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetPort(),
						"actual":   port,
					}).Warn("Port does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetPort(),
						"actual":   port,
					}).Debug("Port matches")
				}
				matchedMask |= IN_PORT

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
				cmpType := uint32(common.GetEthernetLayer(frame).EthernetType)
				if dot1q := common.GetDot1QLayer(frame); dot1q != nil {
					cmpType = uint32(dot1q.Type)
				}
				if ofbfield.GetOfbField().GetEthType() != cmpType {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": layers.EthernetType(ofbfield.GetOfbField().GetEthType()),
						"actual":   common.GetEthernetLayer(frame).EthernetType,
					}).Warn("Frame type does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": layers.EthernetType(ofbfield.GetOfbField().GetEthType()),
						"actual":   common.GetEthernetLayer(frame).EthernetType,
					}).Debug("Frame type matches")
				}
				matchedMask |= ETH_TYPE

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
				if ofbfield.GetOfbField().GetIpProto() != uint32(common.GetIpLayer(frame).Protocol) {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetIpProto(),
						"actual":   common.GetIpLayer(frame).Protocol,
					}).Warn("IP protocol does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetIpProto(),
						"actual":   common.GetIpLayer(frame).Protocol,
					}).Debug("IP protocol matches")
				}
				matchedMask |= IP_PROTO

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
				expectedVlan := ofbfield.GetOfbField().GetVlanVid()
				dot1q := common.GetDot1QLayer(frame)

				if (expectedVlan&4096 == 0) != (dot1q == nil) {
					common.Logger().WithFields(logrus.Fields{
						"device":       o,
						"flow":         flow,
						"expectedVlan": expectedVlan,
						"vlanBitwise":  expectedVlan & 4096,
						"dot1q":        dot1q,
					}).Warn("VLAN condition not met")
					return 0, nil
				}
				if dot1q != nil {
					if uint32(dot1q.VLANIdentifier) != (expectedVlan & 4095) {
						common.Logger().WithFields(logrus.Fields{
							"device":   o,
							"flow":     flow,
							"expected": expectedVlan,
							"actual":   uint32(dot1q.VLANIdentifier),
						}).Warn("VLAN VID does not match")
						return 0, nil
					} else {
						common.Logger().WithFields(logrus.Fields{
							"device":   o,
							"flow":     flow,
							"expected": expectedVlan,
							"actual":   uint32(dot1q.VLANIdentifier),
						}).Debug("VLAN VID matches")
					}
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device": o,
						"flow":   flow,
					}).Warn("VLAN VID missing. Not dot1q encapsulation")
				}
				matchedMask |= VLAN_VID

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
				if ofbfield.GetOfbField().GetVlanPcp() != uint32(common.GetDot1QLayer(frame).Priority) {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetVlanPcp(),
						"actual":   uint32(common.GetDot1QLayer(frame).Priority),
					}).Warn("VLAN priority does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetVlanPcp(),
						"actual":   uint32(common.GetDot1QLayer(frame).Priority),
					}).Debug("VLAN priority matches")
				}
				matchedMask |= VLAN_PCP

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
				dstIpRaw := ofbfield.GetOfbField().GetIpv4Dst()
				dstIp := net.IPv4(
					byte((dstIpRaw>>24)&0xFF),
					byte((dstIpRaw>>16)&0xFF),
					byte((dstIpRaw>>8)&0xFF),
					byte(dstIpRaw&0xFF))

				if !dstIp.Equal(common.GetIpLayer(frame).DstIP) {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": dstIp,
						"actual":   common.GetIpLayer(frame).DstIP,
					}).Warn("IPv4 destination does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": dstIp,
						"actual":   common.GetIpLayer(frame).DstIP,
					}).Debug("IPv4 destination matches")

				}
				matchedMask |= IPV4_DST

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
				if ofbfield.GetOfbField().GetUdpSrc() != uint32(common.GetUdpLayer(frame).SrcPort) {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetUdpSrc(),
						"actual":   common.GetUdpLayer(frame).SrcPort,
					}).Warn("UDP source port does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetUdpSrc(),
						"actual":   common.GetUdpLayer(frame).SrcPort,
					}).Debug("UDP source port matches")
				}
				matchedMask |= UDP_SRC

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
				if ofbfield.GetOfbField().GetUdpDst() != uint32(common.GetUdpLayer(frame).DstPort) {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetUdpDst(),
						"actual":   common.GetUdpLayer(frame).DstPort,
					}).Warn("UDP destination port does not match")
					return 0, nil
				} else {
					common.Logger().WithFields(logrus.Fields{
						"device":   o,
						"flow":     flow,
						"expected": ofbfield.GetOfbField().GetUdpDst(),
						"actual":   common.GetUdpLayer(frame).DstPort,
					}).Debug("UDP destination port does matches")
				}
				matchedMask |= UDP_DST

			case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
				common.Logger().WithFields(logrus.Fields{
					"device": o,
					"flow":   flow,
				}).Warn("Skipping metadata")
				continue

			default:
				common.Logger().WithFields(logrus.Fields{
					"device": o,
					"flow":   flow,
					"type":   ofbfield.GetOfbField().Type,
				}).Warn("Field type not implemented")
			}
		}
	}
	return matchedMask, nil
}

/*
processActions applies transformation instructions to a frame that met all the flow criteria
*/
func (o *PonSimDevice) processActions(
	ctx context.Context,
	flow *openflow_13.OfpFlowStats,
	frame gopacket.Packet,
) (uint32, gopacket.Packet) {
	var egressPort uint32
	var retFrame gopacket.Packet = frame

	common.Logger().WithFields(logrus.Fields{
		"device": o,
		"flow":   flow,
		"frame":  retFrame,
	}).Info("Processing actions")

	for _, instruction := range flow.Instructions {
		common.Logger().WithFields(logrus.Fields{
			"device":      o,
			"flow":        flow,
			"frame":       retFrame,
			"instruction": instruction,
		}).Debug("Processing actions - Instruction entry")
		if instruction.Type == uint32(openflow_13.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
			for _, action := range instruction.GetActions().GetActions() {
				common.Logger().WithFields(logrus.Fields{
					"device":     o,
					"flow":       flow,
					"frame":      retFrame,
					"action":     action,
					"actionType": action.Type,
				}).Debug("Processing actions - Action entry")

				switch action.Type {
				case openflow_13.OfpActionType_OFPAT_OUTPUT:
					common.Logger().WithFields(logrus.Fields{
						"device": o,
						"flow":   flow,
						"frame":  retFrame,
					}).Debug("Processing action OFPAT output")
					egressPort = action.GetOutput().Port

				case openflow_13.OfpActionType_OFPAT_POP_VLAN:
					common.Logger().WithFields(logrus.Fields{
						"device": o,
						"flow":   flow,
						"frame":  retFrame,
					}).Debug("Processing action OFPAT POP VLAN")
					if shim := common.GetDot1QLayer(retFrame); shim != nil {
						if eth := common.GetEthernetLayer(retFrame); eth != nil {
							ethernetLayer := &layers.Ethernet{
								SrcMAC:       eth.SrcMAC,
								DstMAC:       eth.DstMAC,
								EthernetType: shim.Type,
							}
							buffer := gopacket.NewSerializeBuffer()
							gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
								ethernetLayer,
								gopacket.Payload(shim.Payload),
							)
							retFrame = gopacket.NewPacket(
								buffer.Bytes(),
								layers.LayerTypeEthernet,
								gopacket.Default,
							)
						} else {
							common.Logger().WithFields(logrus.Fields{
								"device": o,
								"flow":   flow,
								"frame":  retFrame,
							}).Warn("No ETH found while processing POP VLAN action")
						}
					} else {
						common.Logger().WithFields(logrus.Fields{
							"device": o,
							"flow":   flow,
							"frame":  retFrame,
						}).Warn("No DOT1Q found while processing POP VLAN action")
					}
				case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
					if eth := common.GetEthernetLayer(retFrame); eth != nil {
						ethernetLayer := &layers.Ethernet{
							SrcMAC:       eth.SrcMAC,
							DstMAC:       eth.DstMAC,
							EthernetType: layers.EthernetType(action.GetPush().GetEthertype()),
						}
						dot1qLayer := &layers.Dot1Q{
							Type: eth.EthernetType,
						}

						buffer := gopacket.NewSerializeBuffer()
						gopacket.SerializeLayers(
							buffer,
							gopacket.SerializeOptions{
								FixLengths: false,
							},
							ethernetLayer,
							dot1qLayer,
							gopacket.Payload(eth.Payload),
						)
						retFrame = gopacket.NewPacket(
							buffer.Bytes(),
							layers.LayerTypeEthernet,
							gopacket.Default,
						)
					} else {
						common.Logger().WithFields(logrus.Fields{
							"device": o,
							"flow":   flow,
							"frame":  retFrame,
						}).Warn("No ETH found while processing PUSH VLAN action")
					}
				case openflow_13.OfpActionType_OFPAT_SET_FIELD:
					common.Logger().WithFields(logrus.Fields{
						"device": o,
						"flow":   flow,
						"frame":  retFrame,
					}).Debug("Processing action OFPAT SET FIELD")
					if action.GetSetField().GetField().GetOxmClass() ==
						openflow_13.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
						field := action.GetSetField().GetField().GetOfbField()

						switch field.Type {
						case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
							common.Logger().WithFields(logrus.Fields{
								"device": o,
								"flow":   flow,
								"frame":  retFrame,
							}).Debug("Processing action OFPAT SET FIELD - VLAN VID")
							if shim := common.GetDot1QLayer(retFrame); shim != nil {
								eth := common.GetEthernetLayer(retFrame)
								buffer := gopacket.NewSerializeBuffer()

								var dot1qLayer *layers.Dot1Q
								var ethernetLayer *layers.Ethernet
								ethernetLayer = &layers.Ethernet{
									SrcMAC:       eth.SrcMAC,
									DstMAC:       eth.DstMAC,
									EthernetType: eth.EthernetType,
								}

								dot1qLayer = &layers.Dot1Q{
									Type:           shim.Type,
									VLANIdentifier: uint16(field.GetVlanVid() & 4095),
								}

								gopacket.SerializeLayers(
									buffer,
									gopacket.SerializeOptions{},
									ethernetLayer,
									dot1qLayer,
									gopacket.Payload(shim.LayerPayload()),
								)
								retFrame = gopacket.NewPacket(
									buffer.Bytes(),
									layers.LayerTypeEthernet,
									gopacket.Default,
								)

								common.Logger().WithFields(logrus.Fields{
									"device":    o,
									"flow":      flow,
									"frame":     retFrame,
									"frameDump": retFrame.Dump(),
									"vlanVid":   shim.VLANIdentifier,
								}).Info("Setting DOT1Q VLAN VID")
							} else {
								common.Logger().WithFields(logrus.Fields{
									"device": o,
									"flow":   flow,
									"frame":  retFrame,
								}).Warn("No DOT1Q found while setting VLAN VID")
							}

						case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
							common.Logger().WithFields(logrus.Fields{
								"device": o,
								"flow":   flow,
								"frame":  retFrame,
							}).Debug("Processing action OFPAT SET FIELD - VLAN PCP")
							if shim := common.GetDot1QLayer(retFrame); shim != nil {
								shim.Priority = uint8(field.GetVlanPcp())
								common.Logger().WithFields(logrus.Fields{
									"device":   o,
									"flow":     flow,
									"frame":    retFrame,
									"priority": shim.Priority,
								}).Info("Setting DOT1Q VLAN PCP")
							} else {
								common.Logger().WithFields(logrus.Fields{
									"device": o,
									"flow":   flow,
									"frame":  retFrame,
								}).Warn("No DOT1Q found while setting VLAN PCP")
							}
						default:
							common.Logger().WithFields(logrus.Fields{
								"device": o,
								"flow":   flow,
								"frame":  retFrame,
								"type":   field.Type,
							}).Warn("Set field not implemented for this type")
						}
					} else {
						common.Logger().WithFields(logrus.Fields{
							"device": o,
							"flow":   flow,
							"frame":  retFrame,
						}).Warn("Field not of type OF-BASIC")
					}
				default:
					common.Logger().WithFields(logrus.Fields{
						"device": o,
						"flow":   flow,
						"frame":  retFrame,
						"type":   action.Type,
					}).Warn("Action type not implemented")
				}
			}
		}
	}

	common.Logger().WithFields(logrus.Fields{
		"device":     o,
		"flow":       flow,
		"egressPort": egressPort,
		"retFrame":   retFrame,
	}).Debug("Processed actions")

	return egressPort, retFrame
}
