blob: 3e31e3cccdf0c467d0c5ccb462229547cdc613de [file] [log] [blame]
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001/*
2 * Copyright 2018-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 */
16
17package packetHandlers
18
19import (
20 "errors"
21 "github.com/google/gopacket"
22 "github.com/google/gopacket/layers"
23)
24
25func PushSingleTag(tag int, pkt gopacket.Packet) (gopacket.Packet, error) {
26 // TODO can this method be semplified?
27 if eth := getEthernetLayer(pkt); eth != nil {
28 ethernetLayer := &layers.Ethernet{
29 SrcMAC: eth.SrcMAC,
30 DstMAC: eth.DstMAC,
31 EthernetType: 0x8100,
32 }
33
34 dot1qLayer := &layers.Dot1Q{
35 Type: eth.EthernetType,
36 VLANIdentifier: uint16(tag),
37 }
38
39 buffer := gopacket.NewSerializeBuffer()
40 gopacket.SerializeLayers(
41 buffer,
42 gopacket.SerializeOptions{
43 FixLengths: false,
44 },
45 ethernetLayer,
46 dot1qLayer,
47 gopacket.Payload(eth.Payload),
48 )
49 ret := gopacket.NewPacket(
50 buffer.Bytes(),
51 layers.LayerTypeEthernet,
52 gopacket.Default,
53 )
54
55 return ret, nil
56 }
57 return nil, errors.New("Couldn't extract LayerTypeEthernet from packet")
58}
59
60func PopSingleTag(pkt gopacket.Packet) (gopacket.Packet, error) {
61 layer, err := getDot1QLayer(pkt)
62 if err != nil {
63 return nil, err
64 }
65
66 if eth := getEthernetLayer(pkt); eth != nil {
67 ethernetLayer := &layers.Ethernet{
68 SrcMAC: eth.SrcMAC,
69 DstMAC: eth.DstMAC,
70 EthernetType: layer.Type,
71 }
72 buffer := gopacket.NewSerializeBuffer()
73 gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
74 ethernetLayer,
75 gopacket.Payload(layer.Payload),
76 )
77 retpkt := gopacket.NewPacket(
78 buffer.Bytes(),
79 layers.LayerTypeEthernet,
80 gopacket.Default,
81 )
82
83 return retpkt, nil
84 }
85 return nil, errors.New("no-ethernet-layer")
86}
87
88func PopDoubleTag(pkt gopacket.Packet) (gopacket.Packet, error) {
89 packet, err := PopSingleTag(pkt)
90 if err != nil {
91 return nil, err
92 }
93 packet, err = PopSingleTag(packet)
94 if err != nil {
95 return nil, err
96 }
97 return packet, nil
98}
99
100func getEthernetLayer(pkt gopacket.Packet) *layers.Ethernet {
101 eth := &layers.Ethernet{}
102 if ethLayer := pkt.Layer(layers.LayerTypeEthernet); ethLayer != nil {
103 eth, _ = ethLayer.(*layers.Ethernet)
104 }
105 return eth
106}
107
108func getDot1QLayer(pkt gopacket.Packet) (*layers.Dot1Q, error) {
109 dot1q := &layers.Dot1Q{}
110 if dot1qLayer := pkt.Layer(layers.LayerTypeDot1Q); dot1qLayer != nil {
111 dot1q = dot1qLayer.(*layers.Dot1Q)
112 return dot1q, nil
113 }
114 return nil, errors.New("no-dot1q-layer-in-packet")
115}
116
117func getVlanTag(pkt gopacket.Packet) (uint16, error) {
118 dot1q, err := getDot1QLayer(pkt)
119 if err != nil {
120 return 0, err
121 }
122 return dot1q.VLANIdentifier, nil
123}