blob: c7db7ebe6f8c1e5f6c6d64f9a9b46247e4deff30 [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"
23 "github.com/google/gopacket"
24 "github.com/google/gopacket/layers"
25 "github.com/looplab/fsm"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070026 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070027 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
28 omci "github.com/opencord/omci-sim"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080029 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070030 log "github.com/sirupsen/logrus"
31 "net"
32 "reflect"
Matteo Scandolofe9ac252019-10-25 11:40:17 -070033 "strconv"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070034)
35
Matteo Scandolo075b1892019-10-07 12:11:07 -070036var GetGemPortId = omci.GetGemPortId
37
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070038var dhcpLogger = log.WithFields(log.Fields{
39 "module": "DHCP",
40})
41
42var defaultParamsRequestList = []layers.DHCPOpt{
43 layers.DHCPOptSubnetMask,
44 layers.DHCPOptBroadcastAddr,
45 layers.DHCPOptTimeOffset,
46 layers.DHCPOptRouter,
47 layers.DHCPOptDomainName,
48 layers.DHCPOptDNS,
49 layers.DHCPOptDomainSearch,
50 layers.DHCPOptHostname,
51 layers.DHCPOptNetBIOSTCPNS,
52 layers.DHCPOptNetBIOSTCPScope,
53 layers.DHCPOptInterfaceMTU,
54 layers.DHCPOptClasslessStaticRoute,
55 layers.DHCPOptNTPServers,
56}
57
Matteo Scandolo40e067f2019-10-16 16:59:41 -070058func createDefaultDHCPReq(intfId uint32, onuId uint32, mac net.HardwareAddr) layers.DHCPv4 {
Matteo Scandolofe9ac252019-10-25 11:40:17 -070059 // NOTE we want to generate a unique XID, the easiest way is to concat the PON ID and the ONU ID
60 // we increment them by one otherwise:
61 // - PON: 0 ONU: 62 = 062 -> 62
62 // - PON: 6 ONU: 2 = 62 -> 62
63 xid, err := strconv.Atoi(fmt.Sprintf("%d%d", intfId+1, onuId+1))
64 if err != nil {
65 log.Fatal("Can't generate unique XID for ONU")
66 }
67
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070068 return layers.DHCPv4{
69 Operation: layers.DHCPOpRequest,
70 HardwareType: layers.LinkTypeEthernet,
71 HardwareLen: 6,
72 HardwareOpts: 0,
Matteo Scandolofe9ac252019-10-25 11:40:17 -070073 Xid: uint32(xid),
Matteo Scandolo40e067f2019-10-16 16:59:41 -070074 ClientHWAddr: mac,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070075 }
76}
77
Matteo Scandolofe9ac252019-10-25 11:40:17 -070078func createDefaultOpts(intfId uint32, onuId uint32) []layers.DHCPOption {
79 hostname := []byte(fmt.Sprintf("%d.%d.bbsim.onf.org", intfId, onuId))
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070080 opts := []layers.DHCPOption{}
81 opts = append(opts, layers.DHCPOption{
82 Type: layers.DHCPOptHostname,
83 Data: hostname,
84 Length: uint8(len(hostname)),
85 })
86
87 bytes := []byte{}
88 for _, option := range defaultParamsRequestList {
89 bytes = append(bytes, byte(option))
90 }
91
92 opts = append(opts, layers.DHCPOption{
93 Type: layers.DHCPOptParamsRequest,
94 Data: bytes,
95 Length: uint8(len(bytes)),
96 })
97 return opts
98}
99
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700100func createDHCPDisc(intfId uint32, onuId uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
101 dhcpLayer := createDefaultDHCPReq(intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700102 defaultOpts := createDefaultOpts(intfId, onuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700103 dhcpLayer.Options = append([]layers.DHCPOption{layers.DHCPOption{
104 Type: layers.DHCPOptMessageType,
105 Data: []byte{byte(layers.DHCPMsgTypeDiscover)},
106 Length: 1,
107 }}, defaultOpts...)
108
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700109 data := []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
110 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
111 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
112 Type: layers.DHCPOptClientID,
113 Data: data,
114 Length: uint8(len(data)),
115 })
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700116
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700117 return &dhcpLayer
118}
119
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700120func createDHCPReq(intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
121 dhcpLayer := createDefaultDHCPReq(intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700122 defaultOpts := createDefaultOpts(intfId, onuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700123
124 dhcpLayer.Options = append(defaultOpts, layers.DHCPOption{
125 Type: layers.DHCPOptMessageType,
126 Data: []byte{byte(layers.DHCPMsgTypeRequest)},
127 Length: 1,
128 })
129
130 data := []byte{182, 21, 0, 128}
131 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
132 Type: layers.DHCPOptServerID,
133 Data: data,
134 Length: uint8(len(data)),
135 })
136
137 data = []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700138 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700139 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
140 Type: layers.DHCPOptClientID,
141 Data: data,
142 Length: uint8(len(data)),
143 })
144
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700145 // 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 -0700146 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
147 Type: layers.DHCPOptRequestIP,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700148 Data: offeredIp,
149 Length: uint8(len(offeredIp)),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700150 })
151 return &dhcpLayer
152}
153
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800154func serializeDHCPPacket(intfId uint32, onuId uint32, cTag int, srcMac net.HardwareAddr, dhcp *layers.DHCPv4) ([]byte, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700155 buffer := gopacket.NewSerializeBuffer()
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800156
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700157 options := gopacket.SerializeOptions{
158 ComputeChecksums: true,
159 FixLengths: true,
160 }
161
162 ethernetLayer := &layers.Ethernet{
163 SrcMAC: srcMac,
164 DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
165 EthernetType: layers.EthernetTypeIPv4,
166 }
167
168 ipLayer := &layers.IPv4{
169 Version: 4,
170 TOS: 0x10,
171 TTL: 128,
172 SrcIP: []byte{0, 0, 0, 0},
173 DstIP: []byte{255, 255, 255, 255},
174 Protocol: layers.IPProtocolUDP,
175 }
176
177 udpLayer := &layers.UDP{
178 SrcPort: 68,
179 DstPort: 67,
180 }
181
182 udpLayer.SetNetworkLayerForChecksum(ipLayer)
183 if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800184 dhcpLogger.Error("SerializeLayers")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700185 return nil, err
186 }
187
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800188 untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
189
190 taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt)
191 if err != nil {
192 dhcpLogger.Error("TagPacket")
193 return nil, err
194 }
195
196 return gopacket.Payload(taggedPkt.Data()), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700197}
198
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700199func GetDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700200 layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
201 dhcp, _ := layerDHCP.(*layers.DHCPv4)
202 if dhcp == nil {
203 return nil, errors.New("Failed-to-extract-DHCP-layer")
204 }
205 return dhcp, nil
206}
207
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700208func GetDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700209 for _, option := range dhcp.Options {
210 if option.Type == layers.DHCPOptMessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700211 if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeDiscover)}) {
212 return layers.DHCPMsgTypeDiscover, nil
213 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700214 return layers.DHCPMsgTypeOffer, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700215 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRequest)}) {
216 return layers.DHCPMsgTypeRequest, nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700217 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeAck)}) {
218 return layers.DHCPMsgTypeAck, nil
219 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRelease)}) {
220 return layers.DHCPMsgTypeRelease, nil
221 } else {
222 msg := fmt.Sprintf("This type %x is not supported", option.Data)
223 return 0, errors.New(msg)
224 }
225 }
226 }
227 return 0, errors.New("Failed to extract MsgType from dhcp")
228}
229
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700230// returns the DHCP Layer type or error if it's not a DHCP Packet
231func GetDhcpPacketType(pkt gopacket.Packet) (string, error) {
232 dhcpLayer, err := GetDhcpLayer(pkt)
233 if err != nil {
234 return "", err
235 }
236 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
237 if err != nil {
238 return "", err
239 }
240
241 return dhcpMessageType.String(), nil
242}
243
Matteo Scandolo27428702019-10-11 16:21:16 -0700244func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, stream bbsim.Stream) error {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700245 // FIXME unify sendDHCPPktIn and sendEapolPktIn methods
Matteo Scandolo075b1892019-10-07 12:11:07 -0700246 gemid, err := GetGemPortId(msg.IntfId, msg.OnuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700247 if err != nil {
248 dhcpLogger.WithFields(log.Fields{
249 "OnuId": msg.OnuId,
250 "IntfId": msg.IntfId,
251 }).Errorf("Can't retrieve GemPortId: %s", err)
252 return err
253 }
254 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
Matteo Scandolo27428702019-10-11 16:21:16 -0700255 IntfType: "pon",
256 IntfId: msg.IntfId,
257 GemportId: uint32(gemid),
258 Pkt: msg.Bytes,
259 PortNo: portNo,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700260 }}
261
262 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
263 dhcpLogger.Errorf("Fail to send DHCP PktInd indication. %v", err)
264 return err
265 }
266 return nil
267}
268
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800269func sendDHCPRequest(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, cTag int, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, offeredIp net.IP, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700270 dhcp := createDHCPReq(ponPortId, onuId, onuHwAddress, offeredIp)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800271 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700272
273 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700274 dhcpLogger.WithFields(log.Fields{
275 "OnuId": onuId,
276 "IntfId": ponPortId,
277 "OnuSn": serialNumber,
278 "OfferedIp": offeredIp.String(),
279 }).Errorf("Cannot serializeDHCPPacket: %s", err)
280 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
281 return err
282 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700283 return err
284 }
285 // NOTE I don't think we need to tag the packet
286 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
287
288 msg := bbsim.ByteMsg{
289 IntfId: ponPortId,
290 OnuId: onuId,
291 Bytes: pkt,
292 }
293
Matteo Scandolo27428702019-10-11 16:21:16 -0700294 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700295 dhcpLogger.WithFields(log.Fields{
296 "OnuId": onuId,
297 "IntfId": ponPortId,
298 "OnuSn": serialNumber,
299 }).Errorf("Cannot sendDHCPPktIn: %s", err)
300 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
301 return err
302 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700303 return err
304 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700305
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700306 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700307 "OnuId": onuId,
308 "IntfId": ponPortId,
309 "OnuSn": serialNumber,
310 "OfferedIp": offeredIp.String(),
311 }).Infof("DHCPRequest Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700312 return nil
313}
314
Matteo Scandolo075b1892019-10-07 12:11:07 -0700315func updateDhcpFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
316 if err := onuStateMachine.Event("dhcp_failed"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700317 dhcpLogger.WithFields(log.Fields{
318 "OnuId": onuId,
319 "IntfId": ponPortId,
320 "OnuSn": serialNumber,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700321 }).Errorf("Error while transitioning ONU State %v", err)
322 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700323 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700324 return nil
325}
326
Matteo Scandolo27428702019-10-11 16:21:16 -0700327func SendDHCPDiscovery(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, cTag int, stream bbsim.Stream) error {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700328 dhcp := createDHCPDisc(ponPortId, onuId, onuHwAddress)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800329 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
330
Matteo Scandolo075b1892019-10-07 12:11:07 -0700331 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700332 dhcpLogger.WithFields(log.Fields{
333 "OnuId": onuId,
334 "IntfId": ponPortId,
335 "OnuSn": serialNumber,
336 }).Errorf("Cannot serializeDHCPPacket: %s", err)
337 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
338 return err
339 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700340 return err
341 }
342 // NOTE I don't think we need to tag the packet
343 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
344
345 msg := bbsim.ByteMsg{
346 IntfId: ponPortId,
347 OnuId: onuId,
348 Bytes: pkt,
349 }
350
Matteo Scandolo27428702019-10-11 16:21:16 -0700351 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700352 dhcpLogger.WithFields(log.Fields{
353 "OnuId": onuId,
354 "IntfId": ponPortId,
355 "OnuSn": serialNumber,
356 }).Errorf("Cannot sendDHCPPktIn: %s", err)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700357 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
358 return err
359 }
360 return err
361 }
362 dhcpLogger.WithFields(log.Fields{
363 "OnuId": onuId,
364 "IntfId": ponPortId,
365 "OnuSn": serialNumber,
366 }).Infof("DHCPDiscovery Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700367
368 if err := onuStateMachine.Event("dhcp_discovery_sent"); err != nil {
369 dhcpLogger.WithFields(log.Fields{
370 "OnuId": onuId,
371 "IntfId": ponPortId,
372 "OnuSn": serialNumber,
373 }).Errorf("Error while transitioning ONU State %v", err)
374 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700375 return nil
376}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700377
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700378// FIXME cTag is not used here
Matteo Scandolo27428702019-10-11 16:21:16 -0700379func HandleNextPacket(onuId uint32, ponPortId uint32, serialNumber string, portNo uint32, onuHwAddress net.HardwareAddr, cTag int, onuStateMachine *fsm.FSM, pkt gopacket.Packet, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700380
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700381 dhcpLayer, err := GetDhcpLayer(pkt)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700382 if err != nil {
383 dhcpLogger.WithFields(log.Fields{
384 "OnuId": onuId,
385 "IntfId": ponPortId,
386 "OnuSn": serialNumber,
387 }).Errorf("Can't get DHCP Layer from Packet: %v", err)
388 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
389 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700390 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700391 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700392 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700393 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700394 if err != nil {
395 dhcpLogger.WithFields(log.Fields{
396 "OnuId": onuId,
397 "IntfId": ponPortId,
398 "OnuSn": serialNumber,
399 }).Errorf("Can't get DHCP Message Type from DHCP Layer: %v", err)
400 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
401 return err
402 }
403 return err
404 }
405
406 if dhcpLayer.Operation == layers.DHCPOpReply {
407 if dhcpMessageType == layers.DHCPMsgTypeOffer {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700408 offeredIp := dhcpLayer.YourClientIP
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800409 if err := sendDHCPRequest(ponPortId, onuId, serialNumber, portNo, cTag, onuStateMachine, onuHwAddress, offeredIp, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700410 dhcpLogger.WithFields(log.Fields{
411 "OnuId": onuId,
412 "IntfId": ponPortId,
413 "OnuSn": serialNumber,
414 }).Errorf("Can't send DHCP Request: %s", err)
415 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
416 return err
417 }
418 return err
419 }
420 if err := onuStateMachine.Event("dhcp_request_sent"); err != nil {
421 dhcpLogger.WithFields(log.Fields{
422 "OnuId": onuId,
423 "IntfId": ponPortId,
424 "OnuSn": serialNumber,
425 }).Errorf("Error while transitioning ONU State %v", err)
426 }
427
428 } else if dhcpMessageType == layers.DHCPMsgTypeAck {
429 // NOTE once the ack is received we don't need to do anything but change the state
430 if err := onuStateMachine.Event("dhcp_ack_received"); err != nil {
431 dhcpLogger.WithFields(log.Fields{
432 "OnuId": onuId,
433 "IntfId": ponPortId,
434 "OnuSn": serialNumber,
435 }).Errorf("Error while transitioning ONU State %v", err)
436 }
437 dhcpLogger.WithFields(log.Fields{
438 "OnuId": onuId,
439 "IntfId": ponPortId,
440 "OnuSn": serialNumber,
441 }).Infof("DHCP State machine completed")
442 }
443 // NOTE do we need to care about DHCPMsgTypeRelease??
444 } else {
445 dhcpLogger.WithFields(log.Fields{
446 "OnuId": onuId,
447 "IntfId": ponPortId,
448 "OnuSn": serialNumber,
449 }).Warnf("Unsupported DHCP Operation: %s", dhcpLayer.Operation.String())
450 }
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700451
Matteo Scandolo075b1892019-10-07 12:11:07 -0700452 return nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700453}
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700454
455// This method handle the BBR DHCP Packets
456// BBR does not need to do anything but forward the packets in the correct direction
457func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, sTag int, macAddress net.HardwareAddr, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
458
459 // check if the packet is going:
460 // - outgouing: toward the DHCP
461 // - incoming: toward the ONU
462 isIncoming := packetHandlers.IsIncomingPacket(pkt)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800463 dhcpLogger.Tracef("Is Incoming: %t", isIncoming)
464
465 pkt, err := packetHandlers.PopSingleTag(pkt)
466 if err != nil {
467 dhcpLogger.WithFields(log.Fields{
468 "OnuId": onuId,
469 "IntfId": ponPortId,
470 "OnuSn": serialNumber,
471 "error": err,
472 }).Fatalf("Can't untag packet")
473 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700474
475 dhcpType, err := GetDhcpPacketType(pkt)
476 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800477 dhcpLogger.WithFields(log.Fields{
478 "OnuId": onuId,
479 "IntfId": ponPortId,
480 "OnuSn": serialNumber,
481 "error": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700482 }).Fatalf("Can't find DHCP type for packet")
483 }
484
485 srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
486 dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
487
488 if isIncoming == true {
489
490 onuPacket := openolt.OnuPacket{
491 IntfId: ponPortId,
492 OnuId: onuId,
493 PortNo: onuId,
494 GemportId: 1,
495 Pkt: pkt.Data(),
496 }
497
498 if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800499 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700500 "OnuId": onuId,
501 "IntfId": ponPortId,
502 "OnuSn": serialNumber,
503 "Type": dhcpType,
504 "error": err,
505 }).Error("Failed to send DHCP packet to the ONU")
506 }
507
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800508 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700509 "OnuId": onuId,
510 "IntfId": ponPortId,
511 "OnuSn": serialNumber,
512 "Type": dhcpType,
513 "DstMac": dstMac,
514 "SrcMac": srcMac,
515 "OnuMac": macAddress,
516 }).Infof("Sent DHCP packet to the ONU")
517
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700518 dhcpLayer, _ := GetDhcpLayer(pkt)
519 dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
520 if dhcpMessageType == layers.DHCPMsgTypeAck {
521 doneChannel <- true
522 }
523
524 } else {
525 // double tag the packet and send it to the NNI
526 // NOTE do we need this in the HandleDHCP Packet?
527 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(sTag, sTag, pkt)
528 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800529 dhcpLogger.WithFields(log.Fields{
530 "OnuId": onuId,
531 "IntfId": ponPortId,
532 "OnuSn": serialNumber,
533 "Type": dhcpType,
534 "error": err,
535 }).Error("Failed to add double tag to packet")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700536 }
537
538 pkt := openolt.UplinkPacket{
539 IntfId: 0, // BBSim does not care about which NNI, it has only one
540 Pkt: doubleTaggedPkt.Data(),
541 }
542 if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800543 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700544 "OnuId": onuId,
545 "IntfId": ponPortId,
546 "OnuSn": serialNumber,
547 "Type": dhcpType,
548 "error": err,
549 }).Error("Failed to send DHCP packet out of the NNI Port")
550 }
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800551 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700552 "OnuId": onuId,
553 "IntfId": ponPortId,
554 "OnuSn": serialNumber,
555 "Type": dhcpType,
556 "DstMac": dstMac,
557 "SrcMac": srcMac,
558 "OnuMac": macAddress,
559 }).Infof("Sent DHCP packet out of the NNI Port")
560 }
561 return nil
562}