blob: 1ce71d68d16b9c8b5c08a01ca952a2594817a1a8 [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 Scandolo378b8c92020-04-16 14:34:22 -070058func createDefaultDHCPReq(oltId int, 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:
Matteo Scandolo378b8c92020-04-16 14:34:22 -070061 // - OLT: 0 PON: 0 ONU: 62 = 062 -> 62
62 // - OLT: 0 PON: 6 ONU: 2 = 62 -> 62
63 xid, err := strconv.Atoi(fmt.Sprintf("%d%d%d", oltId+1, intfId+1, onuId+1))
Matteo Scandolofe9ac252019-10-25 11:40:17 -070064 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 Scandolo378b8c92020-04-16 14:34:22 -0700100func createDHCPDisc(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
101 dhcpLayer := createDefaultDHCPReq(oltId, 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,
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700110 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)} //FIXME use the OLT-ID in here
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700111 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 Scandolo378b8c92020-04-16 14:34:22 -0700120func createDHCPReq(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
121 dhcpLayer := createDefaultDHCPReq(oltId, 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 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700254
255 log.WithFields(log.Fields{
256 "OnuId": msg.OnuId,
257 "IntfId": msg.IntfId,
258 "GemPort": gemid,
259 "Type": "DHCP",
260 }).Trace("sending-pkt")
261
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700262 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
Matteo Scandolo27428702019-10-11 16:21:16 -0700263 IntfType: "pon",
264 IntfId: msg.IntfId,
265 GemportId: uint32(gemid),
266 Pkt: msg.Bytes,
267 PortNo: portNo,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700268 }}
269
270 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
271 dhcpLogger.Errorf("Fail to send DHCP PktInd indication. %v", err)
272 return err
273 }
274 return nil
275}
276
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700277func sendDHCPRequest(oltId int, ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, cTag int, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, offeredIp net.IP, stream openolt.Openolt_EnableIndicationServer) error {
278 dhcp := createDHCPReq(oltId, ponPortId, onuId, onuHwAddress, offeredIp)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800279 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700280
281 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700282 dhcpLogger.WithFields(log.Fields{
283 "OnuId": onuId,
284 "IntfId": ponPortId,
285 "OnuSn": serialNumber,
286 "OfferedIp": offeredIp.String(),
287 }).Errorf("Cannot serializeDHCPPacket: %s", err)
288 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
289 return err
290 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700291 return err
292 }
293 // NOTE I don't think we need to tag the packet
294 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
295
296 msg := bbsim.ByteMsg{
297 IntfId: ponPortId,
298 OnuId: onuId,
299 Bytes: pkt,
300 }
301
Matteo Scandolo27428702019-10-11 16:21:16 -0700302 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700303 dhcpLogger.WithFields(log.Fields{
304 "OnuId": onuId,
305 "IntfId": ponPortId,
306 "OnuSn": serialNumber,
307 }).Errorf("Cannot sendDHCPPktIn: %s", err)
308 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
309 return err
310 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700311 return err
312 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700313
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700314 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700315 "OnuId": onuId,
316 "IntfId": ponPortId,
317 "OnuSn": serialNumber,
318 "OfferedIp": offeredIp.String(),
319 }).Infof("DHCPRequest Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700320 return nil
321}
322
Matteo Scandolo075b1892019-10-07 12:11:07 -0700323func updateDhcpFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
324 if err := onuStateMachine.Event("dhcp_failed"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700325 dhcpLogger.WithFields(log.Fields{
326 "OnuId": onuId,
327 "IntfId": ponPortId,
328 "OnuSn": serialNumber,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700329 }).Errorf("Error while transitioning ONU State %v", err)
330 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700331 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700332 return nil
333}
334
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700335func SendDHCPDiscovery(oltId int, ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, cTag int, stream bbsim.Stream) error {
336 dhcp := createDHCPDisc(oltId, ponPortId, onuId, onuHwAddress)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800337 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
338
Matteo Scandolo075b1892019-10-07 12:11:07 -0700339 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700340 dhcpLogger.WithFields(log.Fields{
341 "OnuId": onuId,
342 "IntfId": ponPortId,
343 "OnuSn": serialNumber,
344 }).Errorf("Cannot serializeDHCPPacket: %s", err)
345 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
346 return err
347 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700348 return err
349 }
350 // NOTE I don't think we need to tag the packet
351 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
352
353 msg := bbsim.ByteMsg{
354 IntfId: ponPortId,
355 OnuId: onuId,
356 Bytes: pkt,
357 }
358
Matteo Scandolo27428702019-10-11 16:21:16 -0700359 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700360 dhcpLogger.WithFields(log.Fields{
361 "OnuId": onuId,
362 "IntfId": ponPortId,
363 "OnuSn": serialNumber,
364 }).Errorf("Cannot sendDHCPPktIn: %s", err)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700365 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
366 return err
367 }
368 return err
369 }
370 dhcpLogger.WithFields(log.Fields{
371 "OnuId": onuId,
372 "IntfId": ponPortId,
373 "OnuSn": serialNumber,
374 }).Infof("DHCPDiscovery Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700375
376 if err := onuStateMachine.Event("dhcp_discovery_sent"); err != nil {
377 dhcpLogger.WithFields(log.Fields{
378 "OnuId": onuId,
379 "IntfId": ponPortId,
380 "OnuSn": serialNumber,
381 }).Errorf("Error while transitioning ONU State %v", err)
382 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700383 return nil
384}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700385
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700386// FIXME cTag is not used here
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700387func HandleNextPacket(oltId int, 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 -0700388
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700389 dhcpLayer, err := GetDhcpLayer(pkt)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700390 if err != nil {
391 dhcpLogger.WithFields(log.Fields{
392 "OnuId": onuId,
393 "IntfId": ponPortId,
394 "OnuSn": serialNumber,
395 }).Errorf("Can't get DHCP Layer from Packet: %v", err)
396 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
397 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700398 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700399 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700400 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700401 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700402 if err != nil {
403 dhcpLogger.WithFields(log.Fields{
404 "OnuId": onuId,
405 "IntfId": ponPortId,
406 "OnuSn": serialNumber,
407 }).Errorf("Can't get DHCP Message Type from DHCP Layer: %v", err)
408 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
409 return err
410 }
411 return err
412 }
413
414 if dhcpLayer.Operation == layers.DHCPOpReply {
415 if dhcpMessageType == layers.DHCPMsgTypeOffer {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700416 offeredIp := dhcpLayer.YourClientIP
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700417 if err := sendDHCPRequest(oltId, ponPortId, onuId, serialNumber, portNo, cTag, onuStateMachine, onuHwAddress, offeredIp, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700418 dhcpLogger.WithFields(log.Fields{
419 "OnuId": onuId,
420 "IntfId": ponPortId,
421 "OnuSn": serialNumber,
422 }).Errorf("Can't send DHCP Request: %s", err)
423 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
424 return err
425 }
426 return err
427 }
428 if err := onuStateMachine.Event("dhcp_request_sent"); err != nil {
429 dhcpLogger.WithFields(log.Fields{
430 "OnuId": onuId,
431 "IntfId": ponPortId,
432 "OnuSn": serialNumber,
433 }).Errorf("Error while transitioning ONU State %v", err)
434 }
435
436 } else if dhcpMessageType == layers.DHCPMsgTypeAck {
437 // NOTE once the ack is received we don't need to do anything but change the state
438 if err := onuStateMachine.Event("dhcp_ack_received"); err != nil {
439 dhcpLogger.WithFields(log.Fields{
440 "OnuId": onuId,
441 "IntfId": ponPortId,
442 "OnuSn": serialNumber,
443 }).Errorf("Error while transitioning ONU State %v", err)
444 }
445 dhcpLogger.WithFields(log.Fields{
446 "OnuId": onuId,
447 "IntfId": ponPortId,
448 "OnuSn": serialNumber,
449 }).Infof("DHCP State machine completed")
450 }
451 // NOTE do we need to care about DHCPMsgTypeRelease??
452 } else {
453 dhcpLogger.WithFields(log.Fields{
454 "OnuId": onuId,
455 "IntfId": ponPortId,
456 "OnuSn": serialNumber,
457 }).Warnf("Unsupported DHCP Operation: %s", dhcpLayer.Operation.String())
458 }
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700459
Matteo Scandolo075b1892019-10-07 12:11:07 -0700460 return nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700461}
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700462
463// This method handle the BBR DHCP Packets
464// BBR does not need to do anything but forward the packets in the correct direction
465func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, sTag int, macAddress net.HardwareAddr, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
466
467 // check if the packet is going:
468 // - outgouing: toward the DHCP
469 // - incoming: toward the ONU
470 isIncoming := packetHandlers.IsIncomingPacket(pkt)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800471 dhcpLogger.Tracef("Is Incoming: %t", isIncoming)
472
473 pkt, err := packetHandlers.PopSingleTag(pkt)
474 if err != nil {
475 dhcpLogger.WithFields(log.Fields{
476 "OnuId": onuId,
477 "IntfId": ponPortId,
478 "OnuSn": serialNumber,
479 "error": err,
480 }).Fatalf("Can't untag packet")
481 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700482
483 dhcpType, err := GetDhcpPacketType(pkt)
484 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800485 dhcpLogger.WithFields(log.Fields{
486 "OnuId": onuId,
487 "IntfId": ponPortId,
488 "OnuSn": serialNumber,
489 "error": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700490 }).Fatalf("Can't find DHCP type for packet")
491 }
492
493 srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
494 dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
495
496 if isIncoming == true {
497
498 onuPacket := openolt.OnuPacket{
499 IntfId: ponPortId,
500 OnuId: onuId,
501 PortNo: onuId,
502 GemportId: 1,
503 Pkt: pkt.Data(),
504 }
505
506 if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800507 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700508 "OnuId": onuId,
509 "IntfId": ponPortId,
510 "OnuSn": serialNumber,
511 "Type": dhcpType,
512 "error": err,
513 }).Error("Failed to send DHCP packet to the ONU")
514 }
515
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800516 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700517 "OnuId": onuId,
518 "IntfId": ponPortId,
519 "OnuSn": serialNumber,
520 "Type": dhcpType,
521 "DstMac": dstMac,
522 "SrcMac": srcMac,
523 "OnuMac": macAddress,
524 }).Infof("Sent DHCP packet to the ONU")
525
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700526 dhcpLayer, _ := GetDhcpLayer(pkt)
527 dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
528 if dhcpMessageType == layers.DHCPMsgTypeAck {
529 doneChannel <- true
530 }
531
532 } else {
533 // double tag the packet and send it to the NNI
534 // NOTE do we need this in the HandleDHCP Packet?
535 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(sTag, sTag, pkt)
536 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800537 dhcpLogger.WithFields(log.Fields{
538 "OnuId": onuId,
539 "IntfId": ponPortId,
540 "OnuSn": serialNumber,
541 "Type": dhcpType,
542 "error": err,
543 }).Error("Failed to add double tag to packet")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700544 }
545
546 pkt := openolt.UplinkPacket{
547 IntfId: 0, // BBSim does not care about which NNI, it has only one
548 Pkt: doubleTaggedPkt.Data(),
549 }
550 if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
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 "error": err,
557 }).Error("Failed to send DHCP packet out of the NNI Port")
558 }
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800559 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700560 "OnuId": onuId,
561 "IntfId": ponPortId,
562 "OnuSn": serialNumber,
563 "Type": dhcpType,
564 "DstMac": dstMac,
565 "SrcMac": srcMac,
566 "OnuMac": macAddress,
567 }).Infof("Sent DHCP packet out of the NNI Port")
568 }
569 return nil
570}