blob: ebcb96c6212d410105f49de68e7c822d609ec377 [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
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070060func PushDoubleTag(stag int, ctag int, pkt gopacket.Packet) (gopacket.Packet, error) {
61
62 singleTaggedPkt, err := PushSingleTag(ctag, pkt)
63 if err != nil {
64 return nil, err
65 }
66 doubleTaggedPkt, err := PushSingleTag(stag, singleTaggedPkt)
67 if err != nil {
68 return nil, err
69 }
70
71 return doubleTaggedPkt, nil
72}
73
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070074func PopSingleTag(pkt gopacket.Packet) (gopacket.Packet, error) {
75 layer, err := getDot1QLayer(pkt)
76 if err != nil {
77 return nil, err
78 }
79
80 if eth := getEthernetLayer(pkt); eth != nil {
81 ethernetLayer := &layers.Ethernet{
82 SrcMAC: eth.SrcMAC,
83 DstMAC: eth.DstMAC,
84 EthernetType: layer.Type,
85 }
86 buffer := gopacket.NewSerializeBuffer()
87 gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{},
88 ethernetLayer,
89 gopacket.Payload(layer.Payload),
90 )
91 retpkt := gopacket.NewPacket(
92 buffer.Bytes(),
93 layers.LayerTypeEthernet,
94 gopacket.Default,
95 )
96
97 return retpkt, nil
98 }
99 return nil, errors.New("no-ethernet-layer")
100}
101
102func PopDoubleTag(pkt gopacket.Packet) (gopacket.Packet, error) {
103 packet, err := PopSingleTag(pkt)
104 if err != nil {
105 return nil, err
106 }
107 packet, err = PopSingleTag(packet)
108 if err != nil {
109 return nil, err
110 }
111 return packet, nil
112}
113
114func getEthernetLayer(pkt gopacket.Packet) *layers.Ethernet {
115 eth := &layers.Ethernet{}
116 if ethLayer := pkt.Layer(layers.LayerTypeEthernet); ethLayer != nil {
117 eth, _ = ethLayer.(*layers.Ethernet)
118 }
119 return eth
120}
121
122func getDot1QLayer(pkt gopacket.Packet) (*layers.Dot1Q, error) {
123 dot1q := &layers.Dot1Q{}
124 if dot1qLayer := pkt.Layer(layers.LayerTypeDot1Q); dot1qLayer != nil {
125 dot1q = dot1qLayer.(*layers.Dot1Q)
126 return dot1q, nil
127 }
128 return nil, errors.New("no-dot1q-layer-in-packet")
129}
130
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700131func GetVlanTag(pkt gopacket.Packet) (uint16, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700132 dot1q, err := getDot1QLayer(pkt)
133 if err != nil {
134 return 0, err
135 }
136 return dot1q.VLANIdentifier, nil
137}