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