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