blob: 90186a80264e1de67a9673b24acd289002844b8d [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"
Shrey Baid688b4242020-07-10 20:40:10 +053021
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070022 "github.com/google/gopacket"
23 "github.com/google/gopacket/layers"
24)
25
Matteo Scandolo8d281372020-09-03 16:23:37 -070026func PushSingleTag(tag int, pkt gopacket.Packet, pbit uint8) (gopacket.Packet, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070027 // TODO can this method be semplified?
28 if eth := getEthernetLayer(pkt); eth != nil {
29 ethernetLayer := &layers.Ethernet{
30 SrcMAC: eth.SrcMAC,
31 DstMAC: eth.DstMAC,
32 EthernetType: 0x8100,
33 }
34
35 dot1qLayer := &layers.Dot1Q{
36 Type: eth.EthernetType,
37 VLANIdentifier: uint16(tag),
Matteo Scandolo8d281372020-09-03 16:23:37 -070038 Priority: pbit,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070039 }
40
41 buffer := gopacket.NewSerializeBuffer()
Shrey Baid688b4242020-07-10 20:40:10 +053042 _ = gopacket.SerializeLayers(
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070043 buffer,
44 gopacket.SerializeOptions{
45 FixLengths: false,
46 },
47 ethernetLayer,
48 dot1qLayer,
49 gopacket.Payload(eth.Payload),
50 )
51 ret := gopacket.NewPacket(
52 buffer.Bytes(),
53 layers.LayerTypeEthernet,
54 gopacket.Default,
55 )
56
57 return ret, nil
58 }
59 return nil, errors.New("Couldn't extract LayerTypeEthernet from packet")
60}
61
Matteo Scandolo8d281372020-09-03 16:23:37 -070062func PushDoubleTag(stag int, ctag int, pkt gopacket.Packet, pbit uint8) (gopacket.Packet, error) {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070063
Matteo Scandolo8d281372020-09-03 16:23:37 -070064 singleTaggedPkt, err := PushSingleTag(ctag, pkt, pbit)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070065 if err != nil {
66 return nil, err
67 }
Matteo Scandolo8d281372020-09-03 16:23:37 -070068 doubleTaggedPkt, err := PushSingleTag(stag, singleTaggedPkt, pbit)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070069 if err != nil {
70 return nil, err
71 }
72
73 return doubleTaggedPkt, nil
74}
75
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070076func PopSingleTag(pkt gopacket.Packet) (gopacket.Packet, error) {
77 layer, err := getDot1QLayer(pkt)
78 if err != nil {
79 return nil, err
80 }
81
82 if eth := getEthernetLayer(pkt); eth != nil {
83 ethernetLayer := &layers.Ethernet{
84 SrcMAC: eth.SrcMAC,
85 DstMAC: eth.DstMAC,
86 EthernetType: layer.Type,
87 }
88 buffer := gopacket.NewSerializeBuffer()
Shrey Baid688b4242020-07-10 20:40:10 +053089 _ = gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070090 ethernetLayer,
91 gopacket.Payload(layer.Payload),
92 )
93 retpkt := gopacket.NewPacket(
94 buffer.Bytes(),
95 layers.LayerTypeEthernet,
96 gopacket.Default,
97 )
98
99 return retpkt, nil
100 }
101 return nil, errors.New("no-ethernet-layer")
102}
103
104func PopDoubleTag(pkt gopacket.Packet) (gopacket.Packet, error) {
105 packet, err := PopSingleTag(pkt)
106 if err != nil {
107 return nil, err
108 }
109 packet, err = PopSingleTag(packet)
110 if err != nil {
111 return nil, err
112 }
113 return packet, nil
114}
115
116func getEthernetLayer(pkt gopacket.Packet) *layers.Ethernet {
117 eth := &layers.Ethernet{}
118 if ethLayer := pkt.Layer(layers.LayerTypeEthernet); ethLayer != nil {
119 eth, _ = ethLayer.(*layers.Ethernet)
120 }
121 return eth
122}
123
124func getDot1QLayer(pkt gopacket.Packet) (*layers.Dot1Q, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700125 if dot1qLayer := pkt.Layer(layers.LayerTypeDot1Q); dot1qLayer != nil {
Shrey Baid688b4242020-07-10 20:40:10 +0530126 dot1q := dot1qLayer.(*layers.Dot1Q)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700127 return dot1q, nil
128 }
129 return nil, errors.New("no-dot1q-layer-in-packet")
130}
131
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700132func GetVlanTag(pkt gopacket.Packet) (uint16, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700133 dot1q, err := getDot1QLayer(pkt)
134 if err != nil {
135 return 0, err
136 }
137 return dot1q.VLANIdentifier, nil
138}
Matteo Scandolo8d281372020-09-03 16:23:37 -0700139
140func GetPbit(pkt gopacket.Packet) (uint8, error) {
141 dot1q, err := getDot1QLayer(pkt)
142 if err != nil {
143 return 0, err
144 }
145 return dot1q.Priority, nil
146}
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700147
148// godet inner and outer tag from a packet
149// TODO unit test
150func GetTagsFromPacket(pkt gopacket.Packet) (uint16, uint16, error) {
151 sTag, err := GetVlanTag(pkt)
152 if err != nil {
153 return 0, 0, err
154 }
155 singleTagPkt, err := PopSingleTag(pkt)
156 if err != nil {
157 return 0, 0, err
158 }
159 cTag, err := GetVlanTag(singleTagPkt)
160 if err != nil {
161 return 0, 0, err
162 }
163 return sTag, cTag, nil
164}