blob: a0f5fff9b0f89dcef20084524ed905fc012b892a [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 dhcp
18
19import (
Matteo Scandolo40e067f2019-10-16 16:59:41 -070020 "context"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070021 "errors"
22 "fmt"
Shrey Baid688b4242020-07-10 20:40:10 +053023 "net"
24 "reflect"
25 "strconv"
26
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070027 "github.com/google/gopacket"
28 "github.com/google/gopacket/layers"
29 "github.com/looplab/fsm"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070030 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070031 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080032 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070033 log "github.com/sirupsen/logrus"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070034)
35
36var dhcpLogger = log.WithFields(log.Fields{
37 "module": "DHCP",
38})
39
40var defaultParamsRequestList = []layers.DHCPOpt{
41 layers.DHCPOptSubnetMask,
42 layers.DHCPOptBroadcastAddr,
43 layers.DHCPOptTimeOffset,
44 layers.DHCPOptRouter,
45 layers.DHCPOptDomainName,
46 layers.DHCPOptDNS,
47 layers.DHCPOptDomainSearch,
48 layers.DHCPOptHostname,
49 layers.DHCPOptNetBIOSTCPNS,
50 layers.DHCPOptNetBIOSTCPScope,
51 layers.DHCPOptInterfaceMTU,
52 layers.DHCPOptClasslessStaticRoute,
53 layers.DHCPOptNTPServers,
54}
55
Matteo Scandolo378b8c92020-04-16 14:34:22 -070056func createDefaultDHCPReq(oltId int, intfId uint32, onuId uint32, mac net.HardwareAddr) layers.DHCPv4 {
Matteo Scandolofe9ac252019-10-25 11:40:17 -070057 // NOTE we want to generate a unique XID, the easiest way is to concat the PON ID and the ONU ID
58 // we increment them by one otherwise:
Matteo Scandolo378b8c92020-04-16 14:34:22 -070059 // - OLT: 0 PON: 0 ONU: 62 = 062 -> 62
60 // - OLT: 0 PON: 6 ONU: 2 = 62 -> 62
61 xid, err := strconv.Atoi(fmt.Sprintf("%d%d%d", oltId+1, intfId+1, onuId+1))
Matteo Scandolofe9ac252019-10-25 11:40:17 -070062 if err != nil {
63 log.Fatal("Can't generate unique XID for ONU")
64 }
65
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070066 return layers.DHCPv4{
67 Operation: layers.DHCPOpRequest,
68 HardwareType: layers.LinkTypeEthernet,
69 HardwareLen: 6,
70 HardwareOpts: 0,
Matteo Scandolofe9ac252019-10-25 11:40:17 -070071 Xid: uint32(xid),
Matteo Scandolo40e067f2019-10-16 16:59:41 -070072 ClientHWAddr: mac,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070073 }
74}
75
Matteo Scandolofe9ac252019-10-25 11:40:17 -070076func createDefaultOpts(intfId uint32, onuId uint32) []layers.DHCPOption {
77 hostname := []byte(fmt.Sprintf("%d.%d.bbsim.onf.org", intfId, onuId))
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070078 opts := []layers.DHCPOption{}
79 opts = append(opts, layers.DHCPOption{
80 Type: layers.DHCPOptHostname,
81 Data: hostname,
82 Length: uint8(len(hostname)),
83 })
84
85 bytes := []byte{}
86 for _, option := range defaultParamsRequestList {
87 bytes = append(bytes, byte(option))
88 }
89
90 opts = append(opts, layers.DHCPOption{
91 Type: layers.DHCPOptParamsRequest,
92 Data: bytes,
93 Length: uint8(len(bytes)),
94 })
95 return opts
96}
97
Matteo Scandolo4a036262020-08-17 15:56:13 -070098func createDHCPDisc(oltId int, intfId uint32, onuId uint32, gemPort uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
Matteo Scandolo378b8c92020-04-16 14:34:22 -070099 dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700100 defaultOpts := createDefaultOpts(intfId, onuId)
Shrey Baid688b4242020-07-10 20:40:10 +0530101 dhcpLayer.Options = append([]layers.DHCPOption{{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700102 Type: layers.DHCPOptMessageType,
103 Data: []byte{byte(layers.DHCPMsgTypeDiscover)},
104 Length: 1,
105 }}, defaultOpts...)
106
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700107 data := []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700108 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, byte(intfId), byte(onuId), byte(gemPort)} //FIXME use the OLT-ID in here
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700109 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
110 Type: layers.DHCPOptClientID,
111 Data: data,
112 Length: uint8(len(data)),
113 })
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700114
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700115 return &dhcpLayer
116}
117
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700118func createDHCPReq(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
119 dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700120 defaultOpts := createDefaultOpts(intfId, onuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700121
122 dhcpLayer.Options = append(defaultOpts, layers.DHCPOption{
123 Type: layers.DHCPOptMessageType,
124 Data: []byte{byte(layers.DHCPMsgTypeRequest)},
125 Length: 1,
126 })
127
128 data := []byte{182, 21, 0, 128}
129 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
130 Type: layers.DHCPOptServerID,
131 Data: data,
132 Length: uint8(len(data)),
133 })
134
135 data = []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700136 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700137 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
138 Type: layers.DHCPOptClientID,
139 Data: data,
140 Length: uint8(len(data)),
141 })
142
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700143 // NOTE we should not request a specific IP, or we should request the one that has been offered
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700144 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
145 Type: layers.DHCPOptRequestIP,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700146 Data: offeredIp,
147 Length: uint8(len(offeredIp)),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700148 })
149 return &dhcpLayer
150}
151
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800152func serializeDHCPPacket(intfId uint32, onuId uint32, cTag int, srcMac net.HardwareAddr, dhcp *layers.DHCPv4) ([]byte, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700153 buffer := gopacket.NewSerializeBuffer()
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800154
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700155 options := gopacket.SerializeOptions{
156 ComputeChecksums: true,
157 FixLengths: true,
158 }
159
160 ethernetLayer := &layers.Ethernet{
161 SrcMAC: srcMac,
162 DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
163 EthernetType: layers.EthernetTypeIPv4,
164 }
165
166 ipLayer := &layers.IPv4{
167 Version: 4,
168 TOS: 0x10,
169 TTL: 128,
170 SrcIP: []byte{0, 0, 0, 0},
171 DstIP: []byte{255, 255, 255, 255},
172 Protocol: layers.IPProtocolUDP,
173 }
174
175 udpLayer := &layers.UDP{
176 SrcPort: 68,
177 DstPort: 67,
178 }
179
Shrey Baid688b4242020-07-10 20:40:10 +0530180 _ = udpLayer.SetNetworkLayerForChecksum(ipLayer)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700181 if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800182 dhcpLogger.Error("SerializeLayers")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700183 return nil, err
184 }
185
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800186 untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
187
188 taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt)
189 if err != nil {
190 dhcpLogger.Error("TagPacket")
191 return nil, err
192 }
193
194 return gopacket.Payload(taggedPkt.Data()), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700195}
196
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700197func GetDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700198 layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
199 dhcp, _ := layerDHCP.(*layers.DHCPv4)
200 if dhcp == nil {
201 return nil, errors.New("Failed-to-extract-DHCP-layer")
202 }
203 return dhcp, nil
204}
205
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700206func GetDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700207 for _, option := range dhcp.Options {
208 if option.Type == layers.DHCPOptMessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700209 if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeDiscover)}) {
210 return layers.DHCPMsgTypeDiscover, nil
211 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700212 return layers.DHCPMsgTypeOffer, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700213 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRequest)}) {
214 return layers.DHCPMsgTypeRequest, nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700215 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeAck)}) {
216 return layers.DHCPMsgTypeAck, nil
217 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRelease)}) {
218 return layers.DHCPMsgTypeRelease, nil
219 } else {
220 msg := fmt.Sprintf("This type %x is not supported", option.Data)
221 return 0, errors.New(msg)
222 }
223 }
224 }
225 return 0, errors.New("Failed to extract MsgType from dhcp")
226}
227
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700228// returns the DHCP Layer type or error if it's not a DHCP Packet
229func GetDhcpPacketType(pkt gopacket.Packet) (string, error) {
230 dhcpLayer, err := GetDhcpLayer(pkt)
231 if err != nil {
232 return "", err
233 }
234 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
235 if err != nil {
236 return "", err
237 }
238
239 return dhcpMessageType.String(), nil
240}
241
Matteo Scandolo4a036262020-08-17 15:56:13 -0700242func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, gemPortId uint32, stream bbsim.Stream) error {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700243
244 log.WithFields(log.Fields{
Shrey Baid688b4242020-07-10 20:40:10 +0530245 "OnuId": msg.OnuId,
246 "IntfId": msg.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700247 "GemPort": gemPortId,
Shrey Baid688b4242020-07-10 20:40:10 +0530248 "Type": "DHCP",
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700249 }).Trace("sending-pkt")
250
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700251 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
Matteo Scandolo27428702019-10-11 16:21:16 -0700252 IntfType: "pon",
253 IntfId: msg.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700254 GemportId: gemPortId,
Matteo Scandolo27428702019-10-11 16:21:16 -0700255 Pkt: msg.Bytes,
256 PortNo: portNo,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700257 }}
258
259 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
260 dhcpLogger.Errorf("Fail to send DHCP PktInd indication. %v", err)
261 return err
262 }
263 return nil
264}
265
Matteo Scandolo4a036262020-08-17 15:56:13 -0700266func sendDHCPRequest(oltId int, ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, cTag int, gemPortId uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, offeredIp net.IP, stream bbsim.Stream) error {
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700267 dhcp := createDHCPReq(oltId, ponPortId, onuId, onuHwAddress, offeredIp)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800268 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700269
270 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700271 dhcpLogger.WithFields(log.Fields{
272 "OnuId": onuId,
273 "IntfId": ponPortId,
274 "OnuSn": serialNumber,
275 "OfferedIp": offeredIp.String(),
276 }).Errorf("Cannot serializeDHCPPacket: %s", err)
277 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
278 return err
279 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700280 return err
281 }
282 // NOTE I don't think we need to tag the packet
283 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
284
285 msg := bbsim.ByteMsg{
286 IntfId: ponPortId,
287 OnuId: onuId,
288 Bytes: pkt,
289 }
290
Matteo Scandolo4a036262020-08-17 15:56:13 -0700291 if err := sendDHCPPktIn(msg, portNo, gemPortId, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700292 dhcpLogger.WithFields(log.Fields{
293 "OnuId": onuId,
294 "IntfId": ponPortId,
295 "OnuSn": serialNumber,
296 }).Errorf("Cannot sendDHCPPktIn: %s", err)
297 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
298 return err
299 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700300 return err
301 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700302
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700303 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700304 "OnuId": onuId,
305 "IntfId": ponPortId,
306 "OnuSn": serialNumber,
307 "OfferedIp": offeredIp.String(),
308 }).Infof("DHCPRequest Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700309 return nil
310}
311
Matteo Scandolo075b1892019-10-07 12:11:07 -0700312func updateDhcpFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
313 if err := onuStateMachine.Event("dhcp_failed"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700314 dhcpLogger.WithFields(log.Fields{
315 "OnuId": onuId,
316 "IntfId": ponPortId,
317 "OnuSn": serialNumber,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700318 }).Errorf("Error while transitioning ONU State %v", err)
319 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700320 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700321 return nil
322}
323
Matteo Scandolo4a036262020-08-17 15:56:13 -0700324func SendDHCPDiscovery(oltId int, ponPortId uint32, onuId uint32, cTag int, gemPortId uint32, serialNumber string, portNo uint32, stateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, stream bbsim.Stream) error {
325 dhcp := createDHCPDisc(oltId, ponPortId, onuId, gemPortId, onuHwAddress)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800326 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
327
Matteo Scandolo075b1892019-10-07 12:11:07 -0700328 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700329 dhcpLogger.WithFields(log.Fields{
330 "OnuId": onuId,
331 "IntfId": ponPortId,
332 "OnuSn": serialNumber,
333 }).Errorf("Cannot serializeDHCPPacket: %s", err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700334 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, stateMachine); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700335 return err
336 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700337 return err
338 }
339 // NOTE I don't think we need to tag the packet
340 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
341
342 msg := bbsim.ByteMsg{
343 IntfId: ponPortId,
344 OnuId: onuId,
345 Bytes: pkt,
346 }
347
Matteo Scandolo4a036262020-08-17 15:56:13 -0700348 if err := sendDHCPPktIn(msg, portNo, gemPortId, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700349 dhcpLogger.WithFields(log.Fields{
350 "OnuId": onuId,
351 "IntfId": ponPortId,
352 "OnuSn": serialNumber,
353 }).Errorf("Cannot sendDHCPPktIn: %s", err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700354 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, stateMachine); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700355 return err
356 }
357 return err
358 }
359 dhcpLogger.WithFields(log.Fields{
360 "OnuId": onuId,
361 "IntfId": ponPortId,
362 "OnuSn": serialNumber,
363 }).Infof("DHCPDiscovery Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700364
Matteo Scandolo4a036262020-08-17 15:56:13 -0700365 if err := stateMachine.Event("dhcp_discovery_sent"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700366 dhcpLogger.WithFields(log.Fields{
367 "OnuId": onuId,
368 "IntfId": ponPortId,
369 "OnuSn": serialNumber,
370 }).Errorf("Error while transitioning ONU State %v", err)
371 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700372 return nil
373}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700374
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700375// FIXME cTag is not used here
Matteo Scandolo4a036262020-08-17 15:56:13 -0700376func HandleNextPacket(oltId int, onuId uint32, ponPortId uint32, serialNumber string, portNo uint32, cTag int, gemPortId uint32, onuHwAddress net.HardwareAddr, onuStateMachine *fsm.FSM, pkt gopacket.Packet, stream bbsim.Stream) error {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700377
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700378 dhcpLayer, err := GetDhcpLayer(pkt)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700379 if err != nil {
380 dhcpLogger.WithFields(log.Fields{
381 "OnuId": onuId,
382 "IntfId": ponPortId,
383 "OnuSn": serialNumber,
384 }).Errorf("Can't get DHCP Layer from Packet: %v", err)
385 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
386 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700387 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700388 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700389 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700390 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700391 if err != nil {
392 dhcpLogger.WithFields(log.Fields{
393 "OnuId": onuId,
394 "IntfId": ponPortId,
395 "OnuSn": serialNumber,
396 }).Errorf("Can't get DHCP Message Type from DHCP Layer: %v", err)
397 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
398 return err
399 }
400 return err
401 }
402
403 if dhcpLayer.Operation == layers.DHCPOpReply {
404 if dhcpMessageType == layers.DHCPMsgTypeOffer {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700405 offeredIp := dhcpLayer.YourClientIP
Matteo Scandolo4a036262020-08-17 15:56:13 -0700406 if err := sendDHCPRequest(oltId, ponPortId, onuId, serialNumber, portNo, cTag, gemPortId, onuStateMachine, onuHwAddress, offeredIp, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700407 dhcpLogger.WithFields(log.Fields{
408 "OnuId": onuId,
409 "IntfId": ponPortId,
410 "OnuSn": serialNumber,
411 }).Errorf("Can't send DHCP Request: %s", err)
412 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
413 return err
414 }
415 return err
416 }
417 if err := onuStateMachine.Event("dhcp_request_sent"); err != nil {
418 dhcpLogger.WithFields(log.Fields{
419 "OnuId": onuId,
420 "IntfId": ponPortId,
421 "OnuSn": serialNumber,
422 }).Errorf("Error while transitioning ONU State %v", err)
423 }
424
425 } else if dhcpMessageType == layers.DHCPMsgTypeAck {
426 // NOTE once the ack is received we don't need to do anything but change the state
427 if err := onuStateMachine.Event("dhcp_ack_received"); err != nil {
428 dhcpLogger.WithFields(log.Fields{
429 "OnuId": onuId,
430 "IntfId": ponPortId,
431 "OnuSn": serialNumber,
432 }).Errorf("Error while transitioning ONU State %v", err)
433 }
434 dhcpLogger.WithFields(log.Fields{
435 "OnuId": onuId,
436 "IntfId": ponPortId,
437 "OnuSn": serialNumber,
438 }).Infof("DHCP State machine completed")
439 }
440 // NOTE do we need to care about DHCPMsgTypeRelease??
441 } else {
442 dhcpLogger.WithFields(log.Fields{
443 "OnuId": onuId,
444 "IntfId": ponPortId,
445 "OnuSn": serialNumber,
446 }).Warnf("Unsupported DHCP Operation: %s", dhcpLayer.Operation.String())
447 }
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700448
Matteo Scandolo075b1892019-10-07 12:11:07 -0700449 return nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700450}
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700451
452// This method handle the BBR DHCP Packets
453// BBR does not need to do anything but forward the packets in the correct direction
Matteo Scandolo4a036262020-08-17 15:56:13 -0700454func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700455
456 // check if the packet is going:
457 // - outgouing: toward the DHCP
458 // - incoming: toward the ONU
459 isIncoming := packetHandlers.IsIncomingPacket(pkt)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800460 dhcpLogger.Tracef("Is Incoming: %t", isIncoming)
461
462 pkt, err := packetHandlers.PopSingleTag(pkt)
463 if err != nil {
464 dhcpLogger.WithFields(log.Fields{
465 "OnuId": onuId,
466 "IntfId": ponPortId,
467 "OnuSn": serialNumber,
468 "error": err,
469 }).Fatalf("Can't untag packet")
470 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700471
472 dhcpType, err := GetDhcpPacketType(pkt)
473 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800474 dhcpLogger.WithFields(log.Fields{
475 "OnuId": onuId,
476 "IntfId": ponPortId,
477 "OnuSn": serialNumber,
478 "error": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700479 }).Fatalf("Can't find DHCP type for packet")
480 }
481
482 srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
483 dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
484
Shrey Baid688b4242020-07-10 20:40:10 +0530485 if isIncoming {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700486
487 onuPacket := openolt.OnuPacket{
488 IntfId: ponPortId,
489 OnuId: onuId,
490 PortNo: onuId,
491 GemportId: 1,
492 Pkt: pkt.Data(),
493 }
494
495 if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800496 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700497 "OnuId": onuId,
498 "IntfId": ponPortId,
499 "OnuSn": serialNumber,
500 "Type": dhcpType,
501 "error": err,
502 }).Error("Failed to send DHCP packet to the ONU")
503 }
504
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800505 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700506 "OnuId": onuId,
507 "IntfId": ponPortId,
508 "OnuSn": serialNumber,
509 "Type": dhcpType,
510 "DstMac": dstMac,
511 "SrcMac": srcMac,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700512 }).Infof("Sent DHCP packet to the ONU")
513
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700514 dhcpLayer, _ := GetDhcpLayer(pkt)
515 dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
516 if dhcpMessageType == layers.DHCPMsgTypeAck {
517 doneChannel <- true
518 }
519
520 } else {
521 // double tag the packet and send it to the NNI
Matteo Scandolo4a036262020-08-17 15:56:13 -0700522 // we don't really care about the tags as they are stripped before
523 // the packet is sent to the DHCP server
524 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(900, 900, pkt)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700525 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800526 dhcpLogger.WithFields(log.Fields{
527 "OnuId": onuId,
528 "IntfId": ponPortId,
529 "OnuSn": serialNumber,
530 "Type": dhcpType,
531 "error": err,
532 }).Error("Failed to add double tag to packet")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700533 }
534
535 pkt := openolt.UplinkPacket{
536 IntfId: 0, // BBSim does not care about which NNI, it has only one
537 Pkt: doubleTaggedPkt.Data(),
538 }
539 if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800540 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700541 "OnuId": onuId,
542 "IntfId": ponPortId,
543 "OnuSn": serialNumber,
544 "Type": dhcpType,
545 "error": err,
546 }).Error("Failed to send DHCP packet out of the NNI Port")
547 }
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800548 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700549 "OnuId": onuId,
550 "IntfId": ponPortId,
551 "OnuSn": serialNumber,
552 "Type": dhcpType,
553 "DstMac": dstMac,
554 "SrcMac": srcMac,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700555 }).Infof("Sent DHCP packet out of the NNI Port")
556 }
557 return nil
558}