blob: c13d0030bb157a86b64ae76a639258b2622510da [file] [log] [blame]
Stephane Barbarie35595062018-02-08 08:34:39 -05001package core
2
3import (
4 "context"
5 "github.com/google/gopacket"
6 "github.com/google/gopacket/layers"
7 "github.com/google/gopacket/pcap"
8 "github.com/opencord/voltha/ponsim/v2/common"
9 "github.com/opencord/voltha/protos/go/openflow_13"
10 "github.com/sirupsen/logrus"
11 "net"
12 "sort"
13)
14
15// TODO: Pass-in the certificate information as a structure parameter
16// TODO: Add certification information
17
18type PonSimDevice struct {
19 Name string `json:name`
20 Port int32 `json:port`
21 Address string `json:address`
22 ExternalIf string `json:external_if`
23 InternalIf string `json:internal_if`
24 Promiscuous bool `json:promiscuous`
25 SnapshotLen int32 `json:snapshot_len`
26 AlarmsOn bool `json:alarm_on`
27 AlarmsFreq int `json:alarm_freq`
28 Counter *PonSimMetricCounter `json:counter`
29
30 //*grpc.GrpcSecurity
31
32 flows []*openflow_13.OfpFlowStats `json:-`
33 ingressHandler *pcap.Handle `json:-`
34 egressHandler *pcap.Handle `json:-`
35 links map[int]map[int]interface{} `json:-`
36}
37
38const (
39 UDP_DST = 1
40 UDP_SRC = 2
41 IPV4_DST = 4
42 VLAN_PCP = 8
43 VLAN_VID = 16
44 IP_PROTO = 32
45 ETH_TYPE = 64
46 IN_PORT = 128
47)
48
49/*
50Start performs common setup operations for a ponsim device
51*/
52func (o *PonSimDevice) Start(ctx context.Context) {
53}
54
55/*
56Stop performs common cleanup operations for a ponsim device
57*/
58func (o *PonSimDevice) Stop(ctx context.Context) {
59}
60
61/*
62GetAddress returns the IP/FQDN for the device
63*/
64func (o *PonSimDevice) GetAddress() string {
65 return o.Address
66}
67
68/*
69GetPort return the port assigned to the device
70*/
71func (o *PonSimDevice) GetPort() int32 {
72 return o.Port
73}
74
75/*
76Forward is responsible of processing incoming data, filtering it and redirecting to the
77intended destination
78*/
79func (o *PonSimDevice) Forward(
80 ctx context.Context,
81 port int,
82 frame gopacket.Packet,
83) error {
84 common.Logger().WithFields(logrus.Fields{
85 "device": o,
86 "port": port,
87 "frame": frame,
88 }).Debug("Forwarding packet")
89
90 var err error
91
92 o.Counter.CountRxFrame(port, len(common.GetEthernetLayer(frame).Payload))
93
94 if egressPort, egressFrame := o.processFrame(ctx, port, frame); egressFrame != nil {
95 forwarded := 0
96 links := o.links[int(egressPort)]
97
98 o.Counter.CountTxFrame(int(egressPort), len(common.GetEthernetLayer(egressFrame).Payload))
99
100 for _, link := range links {
101 forwarded += 1
102
103 common.Logger().WithFields(logrus.Fields{
104 "device": o,
105 "egressPort": port,
106 "egressFrame": egressFrame,
107 }).Debug("Forwarding packet to link")
108
109 link.(func(int, gopacket.Packet))(int(egressPort), egressFrame)
110 }
111 if forwarded == 0 {
112 common.Logger().WithFields(logrus.Fields{
113 "device": o,
114 "port": port,
115 "frame": frame,
116 }).Warn("Nothing was forwarded")
117 }
118 } else {
119 common.Logger().WithFields(logrus.Fields{
120 "device": o,
121 "port": egressPort,
122 "frame": egressFrame,
123 }).Error("Failed to properly process frame")
124 }
125
126 return err
127}
128
129/*
130connectNetworkInterfaces opens network interfaces for reading and/or writing packets
131*/
132func (o *PonSimDevice) connectNetworkInterfaces() {
133 common.Logger().WithFields(logrus.Fields{
134 "device": o,
135 }).Debug("Opening network interfaces")
136
137 var err error
138 if o.ingressHandler, err = pcap.OpenLive(
139 o.ExternalIf, o.SnapshotLen, o.Promiscuous, pcap.BlockForever,
140 ); err != nil {
141 common.Logger().WithFields(logrus.Fields{
142 "device": o,
143 "interface": o.ExternalIf,
144 "error": err.Error(),
145 }).Fatal("Unable to open Ingress interface")
146 } else {
147 common.Logger().WithFields(logrus.Fields{
148 "device": o,
149 "interface": o.ExternalIf,
150 }).Info("Opened Ingress interface")
151 }
152
153 if o.egressHandler, err = pcap.OpenLive(
154 o.InternalIf, o.SnapshotLen, o.Promiscuous, pcap.BlockForever,
155 ); err != nil {
156 common.Logger().WithFields(logrus.Fields{
157 "device": o,
158 "interface": o.InternalIf,
159 "error": err.Error(),
160 }).Fatal("Unable to open egress interface")
161 } else {
162 common.Logger().WithFields(logrus.Fields{
163 "device": o,
164 "interface": o.InternalIf,
165 }).Info("Opened egress interface")
166 }
167}
168
169/*
170AddLink assigns a functional operation to a device endpoint
171
172The functional operation is called whenever a packet has been processed
173and the endpoint has been identified as the outgoing interface
174*/
175func (o *PonSimDevice) AddLink(
176 port int,
177 index int,
178 function interface{},
179) error {
180 common.Logger().WithFields(logrus.Fields{
181 "device": o,
182 "port": port,
183 "index": index,
184 }).Debug("Linking port to functional operation")
185
186 if o.links == nil {
187 o.links = make(map[int]map[int]interface{})
188 }
189 if _, ok := o.links[port]; !ok {
190 o.links[port] = make(map[int]interface{})
191 }
192 o.links[port][index] = function
193
194 return nil
195}
196
197/*
198RemoveLink will remove reference a functional operation for a given port and index
199*/
200func (o *PonSimDevice) RemoveLink(
201 port int,
202 index int,
203) error {
204 if _, hasPort := o.links[port]; hasPort {
205 if _, hasIndex := o.links[port][index]; hasIndex {
206 common.Logger().WithFields(logrus.Fields{
207 "device": o,
208 "port": port,
209 "index": index,
210 }).Debug("Removing link functional operation")
211
212 delete(o.links[port], index)
213
214 } else {
215 common.Logger().WithFields(logrus.Fields{
216 "device": o,
217 "port": port,
218 "index": index,
219 }).Warn("No such index for link functional operation")
220
221 }
222 } else {
223 common.Logger().WithFields(logrus.Fields{
224 "device": o,
225 "port": port,
226 "index": index,
227 }).Warn("No such port for functional operation")
228 }
229
230 return nil
231}
232
233/*
234InstallFlows assigns flows to the device in order of priority
235*/
236func (o *PonSimDevice) InstallFlows(
237 ctx context.Context,
238 flows []*openflow_13.OfpFlowStats,
239) error {
240 common.Logger().WithFields(logrus.Fields{
241 "device": o,
242 "flows": flows,
243 }).Debug("Installing flows")
244
245 o.flows = flows
246 sort.Sort(common.SortByPriority(o.flows))
247
248 common.Logger().WithFields(logrus.Fields{
249 "device": o,
250 }).Debug("Installed sorted flows")
251
252 return nil
253}
254
255/*
256processFrame is responsible for matching or discarding a frame based on the configured flows
257*/
258func (o *PonSimDevice) processFrame(
259 ctx context.Context,
260 port int,
261 frame gopacket.Packet,
262) (uint32, gopacket.Packet) {
263 common.Logger().WithFields(logrus.Fields{
264 "device": o,
265 "port": port,
266 "frame": frame,
267 }).Debug("Processing frame")
268
269 var err error
270 var matchedMask int = 0
271 var currentMask int
272 var highestPriority uint32 = 0
273 var matchedFlow *openflow_13.OfpFlowStats = nil
274
275 common.Logger().WithFields(logrus.Fields{
276 "device": o,
277 }).Debug("Looping through flows")
278
279 for _, flow := range o.flows {
280 common.Logger().WithFields(logrus.Fields{
281 "device": o,
282 "flow": flow,
283 }).Debug("Checking flow")
284
285 if matchedFlow != nil && flow.Priority < highestPriority {
286 common.Logger().WithFields(logrus.Fields{
287 "device": o,
288 "matchedFlow": matchedFlow,
289 "priority": highestPriority,
290 }).Debug("Flow has already been matched")
291 break
292 } else {
293 common.Logger().WithFields(logrus.Fields{
294 "device": o,
295 "matchedFlow": matchedFlow,
296 "priority": flow.Priority,
297 "highestPriority": highestPriority,
298 }).Debug("Flow OR Priority requirements not met")
299 }
300
301 highestPriority = flow.Priority
302 if currentMask, err = o.isMatch(ctx, flow, port, frame); err != nil {
303 common.Logger().WithFields(logrus.Fields{
304 "device": o,
305 "flow": flow,
306 "port": port,
307 "frame": frame,
308 "error": err.Error(),
309 }).Error("Problem while matching flow")
310
311 } else if currentMask > matchedMask {
312 matchedMask = currentMask
313 matchedFlow = flow
314
315 common.Logger().WithFields(logrus.Fields{
316 "device": o,
317 "matchedFlow": flow,
318 "port": port,
319 "frame": frame,
320 "matchedMask": matchedMask,
321 }).Debug("Flow matches")
322 }
323 }
324
325 if matchedFlow != nil {
326 egressPort, egressFrame := o.processActions(ctx, matchedFlow, frame)
327
328 common.Logger().WithFields(logrus.Fields{
329 "device": o,
330 "port": port,
331 "egressPort": egressPort,
332 "egressFrame": egressFrame,
333 }).Debug("Processed actions to matched flow")
334
335 return egressPort, egressFrame
336 } else {
337 common.Logger().WithFields(logrus.Fields{
338 "device": o,
339 "port": port,
340 "frame": frame,
341 "matchedMask": matchedMask,
342 }).Warn("Flow was not successfully matched")
343 }
344
345 return 0, nil
346}
347
348/*
349isMatch traverses the criteria of a flow and identify all matching elements of a frame (if any)
350*/
351func (o *PonSimDevice) isMatch(
352 ctx context.Context,
353 flow *openflow_13.OfpFlowStats,
354 port int,
355 frame gopacket.Packet,
356) (int, error) {
357 matchedMask := 0
358
359 for _, ofbfield := range flow.Match.OxmFields {
360 if ofbfield.GetOxmClass() == openflow_13.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
361 switch ofbfield.GetOfbField().Type {
362 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
363 if ofbfield.GetOfbField().GetPort() != uint32(port) {
364 common.Logger().WithFields(logrus.Fields{
365 "device": o,
366 "flow": flow,
367 "expected": ofbfield.GetOfbField().GetPort(),
368 "actual": port,
369 }).Warn("Port does not match")
370 return 0, nil
371 } else {
372 common.Logger().WithFields(logrus.Fields{
373 "device": o,
374 "flow": flow,
375 "expected": ofbfield.GetOfbField().GetPort(),
376 "actual": port,
377 }).Debug("Port matches")
378 }
379 matchedMask |= IN_PORT
380
381 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
382 cmpType := uint32(common.GetEthernetLayer(frame).EthernetType)
383 if dot1q := common.GetDot1QLayer(frame); dot1q != nil {
384 cmpType = uint32(dot1q.Type)
385 }
386 if ofbfield.GetOfbField().GetEthType() != cmpType {
387 common.Logger().WithFields(logrus.Fields{
388 "device": o,
389 "flow": flow,
390 "expected": layers.EthernetType(ofbfield.GetOfbField().GetEthType()),
391 "actual": common.GetEthernetLayer(frame).EthernetType,
392 }).Warn("Frame type does not match")
393 return 0, nil
394 } else {
395 common.Logger().WithFields(logrus.Fields{
396 "device": o,
397 "flow": flow,
398 "expected": layers.EthernetType(ofbfield.GetOfbField().GetEthType()),
399 "actual": common.GetEthernetLayer(frame).EthernetType,
400 }).Debug("Frame type matches")
401 }
402 matchedMask |= ETH_TYPE
403
404 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
405 if ofbfield.GetOfbField().GetIpProto() != uint32(common.GetIpLayer(frame).Protocol) {
406 common.Logger().WithFields(logrus.Fields{
407 "device": o,
408 "flow": flow,
409 "expected": ofbfield.GetOfbField().GetIpProto(),
410 "actual": common.GetIpLayer(frame).Protocol,
411 }).Warn("IP protocol does not match")
412 return 0, nil
413 } else {
414 common.Logger().WithFields(logrus.Fields{
415 "device": o,
416 "flow": flow,
417 "expected": ofbfield.GetOfbField().GetIpProto(),
418 "actual": common.GetIpLayer(frame).Protocol,
419 }).Debug("IP protocol matches")
420 }
421 matchedMask |= IP_PROTO
422
423 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
424 expectedVlan := ofbfield.GetOfbField().GetVlanVid()
425 dot1q := common.GetDot1QLayer(frame)
426
427 if (expectedVlan&4096 == 0) != (dot1q == nil) {
428 common.Logger().WithFields(logrus.Fields{
429 "device": o,
430 "flow": flow,
431 "expectedVlan": expectedVlan,
432 "vlanBitwise": expectedVlan & 4096,
433 "dot1q": dot1q,
434 }).Warn("VLAN condition not met")
435 return 0, nil
436 }
437 if dot1q != nil {
438 if uint32(dot1q.VLANIdentifier) != (expectedVlan & 4095) {
439 common.Logger().WithFields(logrus.Fields{
440 "device": o,
441 "flow": flow,
442 "expected": expectedVlan,
443 "actual": uint32(dot1q.VLANIdentifier),
444 }).Warn("VLAN VID does not match")
445 return 0, nil
446 } else {
447 common.Logger().WithFields(logrus.Fields{
448 "device": o,
449 "flow": flow,
450 "expected": expectedVlan,
451 "actual": uint32(dot1q.VLANIdentifier),
452 }).Debug("VLAN VID matches")
453 }
454 } else {
455 common.Logger().WithFields(logrus.Fields{
456 "device": o,
457 "flow": flow,
458 }).Warn("VLAN VID missing. Not dot1q encapsulation")
459 }
460 matchedMask |= VLAN_VID
461
462 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
463 if ofbfield.GetOfbField().GetVlanPcp() != uint32(common.GetDot1QLayer(frame).Priority) {
464 common.Logger().WithFields(logrus.Fields{
465 "device": o,
466 "flow": flow,
467 "expected": ofbfield.GetOfbField().GetVlanPcp(),
468 "actual": uint32(common.GetDot1QLayer(frame).Priority),
469 }).Warn("VLAN priority does not match")
470 return 0, nil
471 } else {
472 common.Logger().WithFields(logrus.Fields{
473 "device": o,
474 "flow": flow,
475 "expected": ofbfield.GetOfbField().GetVlanPcp(),
476 "actual": uint32(common.GetDot1QLayer(frame).Priority),
477 }).Debug("VLAN priority matches")
478 }
479 matchedMask |= VLAN_PCP
480
481 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IPV4_DST:
482 dstIpRaw := ofbfield.GetOfbField().GetIpv4Dst()
483 dstIp := net.IPv4(
484 byte((dstIpRaw>>24)&0xFF),
485 byte((dstIpRaw>>16)&0xFF),
486 byte((dstIpRaw>>8)&0xFF),
487 byte(dstIpRaw&0xFF))
488
489 if !dstIp.Equal(common.GetIpLayer(frame).DstIP) {
490 common.Logger().WithFields(logrus.Fields{
491 "device": o,
492 "flow": flow,
493 "expected": dstIp,
494 "actual": common.GetIpLayer(frame).DstIP,
495 }).Warn("IPv4 destination does not match")
496 return 0, nil
497 } else {
498 common.Logger().WithFields(logrus.Fields{
499 "device": o,
500 "flow": flow,
501 "expected": dstIp,
502 "actual": common.GetIpLayer(frame).DstIP,
503 }).Debug("IPv4 destination matches")
504
505 }
506 matchedMask |= IPV4_DST
507
508 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
509 if ofbfield.GetOfbField().GetUdpSrc() != uint32(common.GetUdpLayer(frame).SrcPort) {
510 common.Logger().WithFields(logrus.Fields{
511 "device": o,
512 "flow": flow,
513 "expected": ofbfield.GetOfbField().GetUdpSrc(),
514 "actual": common.GetUdpLayer(frame).SrcPort,
515 }).Warn("UDP source port does not match")
516 return 0, nil
517 } else {
518 common.Logger().WithFields(logrus.Fields{
519 "device": o,
520 "flow": flow,
521 "expected": ofbfield.GetOfbField().GetUdpSrc(),
522 "actual": common.GetUdpLayer(frame).SrcPort,
523 }).Debug("UDP source port matches")
524 }
525 matchedMask |= UDP_SRC
526
527 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
528 if ofbfield.GetOfbField().GetUdpDst() != uint32(common.GetUdpLayer(frame).DstPort) {
529 common.Logger().WithFields(logrus.Fields{
530 "device": o,
531 "flow": flow,
532 "expected": ofbfield.GetOfbField().GetUdpDst(),
533 "actual": common.GetUdpLayer(frame).DstPort,
534 }).Warn("UDP destination port does not match")
535 return 0, nil
536 } else {
537 common.Logger().WithFields(logrus.Fields{
538 "device": o,
539 "flow": flow,
540 "expected": ofbfield.GetOfbField().GetUdpDst(),
541 "actual": common.GetUdpLayer(frame).DstPort,
542 }).Debug("UDP destination port does matches")
543 }
544 matchedMask |= UDP_DST
545
546 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_METADATA:
547 common.Logger().WithFields(logrus.Fields{
548 "device": o,
549 "flow": flow,
550 }).Warn("Skipping metadata")
551 continue
552
553 default:
554 common.Logger().WithFields(logrus.Fields{
555 "device": o,
556 "flow": flow,
557 "type": ofbfield.GetOfbField().Type,
558 }).Warn("Field type not implemented")
559 }
560 }
561 }
562 return matchedMask, nil
563}
564
565/*
566processActions applies transformation instructions to a frame that met all the flow criteria
567*/
568func (o *PonSimDevice) processActions(
569 ctx context.Context,
570 flow *openflow_13.OfpFlowStats,
571 frame gopacket.Packet,
572) (uint32, gopacket.Packet) {
573 var egressPort uint32
574 var retFrame gopacket.Packet = frame
575
576 common.Logger().WithFields(logrus.Fields{
577 "device": o,
578 "flow": flow,
579 "frame": retFrame,
580 }).Info("Processing actions")
581
582 for _, instruction := range flow.Instructions {
583 common.Logger().WithFields(logrus.Fields{
584 "device": o,
585 "flow": flow,
586 "frame": retFrame,
587 "instruction": instruction,
588 }).Debug("Processing actions - Instruction entry")
589 if instruction.Type == uint32(openflow_13.OfpInstructionType_OFPIT_APPLY_ACTIONS) {
590 for _, action := range instruction.GetActions().GetActions() {
591 common.Logger().WithFields(logrus.Fields{
592 "device": o,
593 "flow": flow,
594 "frame": retFrame,
595 "action": action,
596 "actionType": action.Type,
597 }).Debug("Processing actions - Action entry")
598
599 switch action.Type {
600 case openflow_13.OfpActionType_OFPAT_OUTPUT:
601 common.Logger().WithFields(logrus.Fields{
602 "device": o,
603 "flow": flow,
604 "frame": retFrame,
605 }).Debug("Processing action OFPAT output")
606 egressPort = action.GetOutput().Port
607
608 case openflow_13.OfpActionType_OFPAT_POP_VLAN:
609 common.Logger().WithFields(logrus.Fields{
610 "device": o,
611 "flow": flow,
612 "frame": retFrame,
613 }).Debug("Processing action OFPAT POP VLAN")
614 if shim := common.GetDot1QLayer(retFrame); shim != nil {
615 if eth := common.GetEthernetLayer(retFrame); eth != nil {
616 ethernetLayer := &layers.Ethernet{
617 SrcMAC: eth.SrcMAC,
618 DstMAC: eth.DstMAC,
619 EthernetType: shim.Type,
620 }
621 buffer := gopacket.NewSerializeBuffer()
622 gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
623 ethernetLayer,
624 gopacket.Payload(shim.Payload),
625 )
626 retFrame = gopacket.NewPacket(
627 buffer.Bytes(),
628 layers.LayerTypeEthernet,
629 gopacket.Default,
630 )
631 } else {
632 common.Logger().WithFields(logrus.Fields{
633 "device": o,
634 "flow": flow,
635 "frame": retFrame,
636 }).Warn("No ETH found while processing POP VLAN action")
637 }
638 } else {
639 common.Logger().WithFields(logrus.Fields{
640 "device": o,
641 "flow": flow,
642 "frame": retFrame,
643 }).Warn("No DOT1Q found while processing POP VLAN action")
644 }
645 case openflow_13.OfpActionType_OFPAT_PUSH_VLAN:
646 if eth := common.GetEthernetLayer(retFrame); eth != nil {
647 ethernetLayer := &layers.Ethernet{
648 SrcMAC: eth.SrcMAC,
649 DstMAC: eth.DstMAC,
650 EthernetType: layers.EthernetType(action.GetPush().GetEthertype()),
651 }
652 dot1qLayer := &layers.Dot1Q{
653 Type: eth.EthernetType,
654 }
655
656 buffer := gopacket.NewSerializeBuffer()
657 gopacket.SerializeLayers(
658 buffer,
659 gopacket.SerializeOptions{
660 FixLengths: false,
661 },
662 ethernetLayer,
663 dot1qLayer,
664 gopacket.Payload(eth.Payload),
665 )
666 retFrame = gopacket.NewPacket(
667 buffer.Bytes(),
668 layers.LayerTypeEthernet,
669 gopacket.Default,
670 )
671 } else {
672 common.Logger().WithFields(logrus.Fields{
673 "device": o,
674 "flow": flow,
675 "frame": retFrame,
676 }).Warn("No ETH found while processing PUSH VLAN action")
677 }
678 case openflow_13.OfpActionType_OFPAT_SET_FIELD:
679 common.Logger().WithFields(logrus.Fields{
680 "device": o,
681 "flow": flow,
682 "frame": retFrame,
683 }).Debug("Processing action OFPAT SET FIELD")
684 if action.GetSetField().GetField().GetOxmClass() ==
685 openflow_13.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
686 field := action.GetSetField().GetField().GetOfbField()
687
688 switch field.Type {
689 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
690 common.Logger().WithFields(logrus.Fields{
691 "device": o,
692 "flow": flow,
693 "frame": retFrame,
694 }).Debug("Processing action OFPAT SET FIELD - VLAN VID")
695 if shim := common.GetDot1QLayer(retFrame); shim != nil {
696 eth := common.GetEthernetLayer(retFrame)
697 buffer := gopacket.NewSerializeBuffer()
698
699 var dot1qLayer *layers.Dot1Q
700 var ethernetLayer *layers.Ethernet
701 ethernetLayer = &layers.Ethernet{
702 SrcMAC: eth.SrcMAC,
703 DstMAC: eth.DstMAC,
704 EthernetType: eth.EthernetType,
705 }
706
707 dot1qLayer = &layers.Dot1Q{
708 Type: shim.Type,
709 VLANIdentifier: uint16(field.GetVlanVid() & 4095),
710 }
711
712 gopacket.SerializeLayers(
713 buffer,
714 gopacket.SerializeOptions{},
715 ethernetLayer,
716 dot1qLayer,
717 gopacket.Payload(shim.LayerPayload()),
718 )
719 retFrame = gopacket.NewPacket(
720 buffer.Bytes(),
721 layers.LayerTypeEthernet,
722 gopacket.Default,
723 )
724
725 common.Logger().WithFields(logrus.Fields{
726 "device": o,
727 "flow": flow,
728 "frame": retFrame,
729 "frameDump": retFrame.Dump(),
730 "vlanVid": shim.VLANIdentifier,
731 }).Info("Setting DOT1Q VLAN VID")
732 } else {
733 common.Logger().WithFields(logrus.Fields{
734 "device": o,
735 "flow": flow,
736 "frame": retFrame,
737 }).Warn("No DOT1Q found while setting VLAN VID")
738 }
739
740 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
741 common.Logger().WithFields(logrus.Fields{
742 "device": o,
743 "flow": flow,
744 "frame": retFrame,
745 }).Debug("Processing action OFPAT SET FIELD - VLAN PCP")
746 if shim := common.GetDot1QLayer(retFrame); shim != nil {
747 shim.Priority = uint8(field.GetVlanPcp())
748 common.Logger().WithFields(logrus.Fields{
749 "device": o,
750 "flow": flow,
751 "frame": retFrame,
752 "priority": shim.Priority,
753 }).Info("Setting DOT1Q VLAN PCP")
754 } else {
755 common.Logger().WithFields(logrus.Fields{
756 "device": o,
757 "flow": flow,
758 "frame": retFrame,
759 }).Warn("No DOT1Q found while setting VLAN PCP")
760 }
761 default:
762 common.Logger().WithFields(logrus.Fields{
763 "device": o,
764 "flow": flow,
765 "frame": retFrame,
766 "type": field.Type,
767 }).Warn("Set field not implemented for this type")
768 }
769 } else {
770 common.Logger().WithFields(logrus.Fields{
771 "device": o,
772 "flow": flow,
773 "frame": retFrame,
774 }).Warn("Field not of type OF-BASIC")
775 }
776 default:
777 common.Logger().WithFields(logrus.Fields{
778 "device": o,
779 "flow": flow,
780 "frame": retFrame,
781 "type": action.Type,
782 }).Warn("Action type not implemented")
783 }
784 }
785 }
786 }
787
788 common.Logger().WithFields(logrus.Fields{
789 "device": o,
790 "flow": flow,
791 "egressPort": egressPort,
792 "retFrame": retFrame,
793 }).Debug("Processed actions")
794
795 return egressPort, retFrame
796}