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