blob: ce71069412a2a714579356b8d177139fcf9d0f16 [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"
29 "github.com/opencord/voltha-protos/go/openolt"
30 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
154func serializeDHCPPacket(intfId uint32, onuId uint32, srcMac net.HardwareAddr, dhcp *layers.DHCPv4) ([]byte, error) {
155 buffer := gopacket.NewSerializeBuffer()
156 options := gopacket.SerializeOptions{
157 ComputeChecksums: true,
158 FixLengths: true,
159 }
160
161 ethernetLayer := &layers.Ethernet{
162 SrcMAC: srcMac,
163 DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
164 EthernetType: layers.EthernetTypeIPv4,
165 }
166
167 ipLayer := &layers.IPv4{
168 Version: 4,
169 TOS: 0x10,
170 TTL: 128,
171 SrcIP: []byte{0, 0, 0, 0},
172 DstIP: []byte{255, 255, 255, 255},
173 Protocol: layers.IPProtocolUDP,
174 }
175
176 udpLayer := &layers.UDP{
177 SrcPort: 68,
178 DstPort: 67,
179 }
180
181 udpLayer.SetNetworkLayerForChecksum(ipLayer)
182 if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
183 return nil, err
184 }
185
186 bytes := buffer.Bytes()
187 return bytes, nil
188}
189
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700190func GetDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700191 layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
192 dhcp, _ := layerDHCP.(*layers.DHCPv4)
193 if dhcp == nil {
194 return nil, errors.New("Failed-to-extract-DHCP-layer")
195 }
196 return dhcp, nil
197}
198
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700199func GetDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700200 for _, option := range dhcp.Options {
201 if option.Type == layers.DHCPOptMessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700202 if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeDiscover)}) {
203 return layers.DHCPMsgTypeDiscover, nil
204 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700205 return layers.DHCPMsgTypeOffer, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700206 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRequest)}) {
207 return layers.DHCPMsgTypeRequest, nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700208 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeAck)}) {
209 return layers.DHCPMsgTypeAck, nil
210 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRelease)}) {
211 return layers.DHCPMsgTypeRelease, nil
212 } else {
213 msg := fmt.Sprintf("This type %x is not supported", option.Data)
214 return 0, errors.New(msg)
215 }
216 }
217 }
218 return 0, errors.New("Failed to extract MsgType from dhcp")
219}
220
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700221// returns the DHCP Layer type or error if it's not a DHCP Packet
222func GetDhcpPacketType(pkt gopacket.Packet) (string, error) {
223 dhcpLayer, err := GetDhcpLayer(pkt)
224 if err != nil {
225 return "", err
226 }
227 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
228 if err != nil {
229 return "", err
230 }
231
232 return dhcpMessageType.String(), nil
233}
234
Matteo Scandolo27428702019-10-11 16:21:16 -0700235func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, stream bbsim.Stream) error {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700236 // FIXME unify sendDHCPPktIn and sendEapolPktIn methods
Matteo Scandolo075b1892019-10-07 12:11:07 -0700237 gemid, err := GetGemPortId(msg.IntfId, msg.OnuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700238 if err != nil {
239 dhcpLogger.WithFields(log.Fields{
240 "OnuId": msg.OnuId,
241 "IntfId": msg.IntfId,
242 }).Errorf("Can't retrieve GemPortId: %s", err)
243 return err
244 }
245 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
Matteo Scandolo27428702019-10-11 16:21:16 -0700246 IntfType: "pon",
247 IntfId: msg.IntfId,
248 GemportId: uint32(gemid),
249 Pkt: msg.Bytes,
250 PortNo: portNo,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700251 }}
252
253 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
254 dhcpLogger.Errorf("Fail to send DHCP PktInd indication. %v", err)
255 return err
256 }
257 return nil
258}
259
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700260func sendDHCPRequest(ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, offeredIp net.IP, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700261 dhcp := createDHCPReq(ponPortId, onuId, onuHwAddress, offeredIp)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700262 pkt, err := serializeDHCPPacket(ponPortId, onuId, onuHwAddress, dhcp)
263
264 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700265 dhcpLogger.WithFields(log.Fields{
266 "OnuId": onuId,
267 "IntfId": ponPortId,
268 "OnuSn": serialNumber,
269 "OfferedIp": offeredIp.String(),
270 }).Errorf("Cannot serializeDHCPPacket: %s", err)
271 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
272 return err
273 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700274 return err
275 }
276 // NOTE I don't think we need to tag the packet
277 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
278
279 msg := bbsim.ByteMsg{
280 IntfId: ponPortId,
281 OnuId: onuId,
282 Bytes: pkt,
283 }
284
Matteo Scandolo27428702019-10-11 16:21:16 -0700285 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700286 dhcpLogger.WithFields(log.Fields{
287 "OnuId": onuId,
288 "IntfId": ponPortId,
289 "OnuSn": serialNumber,
290 }).Errorf("Cannot sendDHCPPktIn: %s", err)
291 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
292 return err
293 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700294 return err
295 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700296
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700297 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700298 "OnuId": onuId,
299 "IntfId": ponPortId,
300 "OnuSn": serialNumber,
301 "OfferedIp": offeredIp.String(),
302 }).Infof("DHCPRequest Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700303 return nil
304}
305
Matteo Scandolo075b1892019-10-07 12:11:07 -0700306func updateDhcpFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
307 if err := onuStateMachine.Event("dhcp_failed"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700308 dhcpLogger.WithFields(log.Fields{
309 "OnuId": onuId,
310 "IntfId": ponPortId,
311 "OnuSn": serialNumber,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700312 }).Errorf("Error while transitioning ONU State %v", err)
313 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700314 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700315 return nil
316}
317
Matteo Scandolo27428702019-10-11 16:21:16 -0700318func 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 -0700319 dhcp := createDHCPDisc(ponPortId, onuId, onuHwAddress)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700320 pkt, err := serializeDHCPPacket(ponPortId, onuId, onuHwAddress, dhcp)
321 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700322 dhcpLogger.WithFields(log.Fields{
323 "OnuId": onuId,
324 "IntfId": ponPortId,
325 "OnuSn": serialNumber,
326 }).Errorf("Cannot serializeDHCPPacket: %s", err)
327 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
328 return err
329 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700330 return err
331 }
332 // NOTE I don't think we need to tag the packet
333 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
334
335 msg := bbsim.ByteMsg{
336 IntfId: ponPortId,
337 OnuId: onuId,
338 Bytes: pkt,
339 }
340
Matteo Scandolo27428702019-10-11 16:21:16 -0700341 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700342 dhcpLogger.WithFields(log.Fields{
343 "OnuId": onuId,
344 "IntfId": ponPortId,
345 "OnuSn": serialNumber,
346 }).Errorf("Cannot sendDHCPPktIn: %s", err)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700347 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
348 return err
349 }
350 return err
351 }
352 dhcpLogger.WithFields(log.Fields{
353 "OnuId": onuId,
354 "IntfId": ponPortId,
355 "OnuSn": serialNumber,
356 }).Infof("DHCPDiscovery Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700357
358 if err := onuStateMachine.Event("dhcp_discovery_sent"); err != nil {
359 dhcpLogger.WithFields(log.Fields{
360 "OnuId": onuId,
361 "IntfId": ponPortId,
362 "OnuSn": serialNumber,
363 }).Errorf("Error while transitioning ONU State %v", err)
364 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700365 return nil
366}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700367
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700368// FIXME cTag is not used here
Matteo Scandolo27428702019-10-11 16:21:16 -0700369func 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 -0700370
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700371 dhcpLayer, err := GetDhcpLayer(pkt)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700372 if err != nil {
373 dhcpLogger.WithFields(log.Fields{
374 "OnuId": onuId,
375 "IntfId": ponPortId,
376 "OnuSn": serialNumber,
377 }).Errorf("Can't get DHCP Layer from Packet: %v", err)
378 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
379 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700380 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700381 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700382 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700383 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700384 if err != nil {
385 dhcpLogger.WithFields(log.Fields{
386 "OnuId": onuId,
387 "IntfId": ponPortId,
388 "OnuSn": serialNumber,
389 }).Errorf("Can't get DHCP Message Type from DHCP Layer: %v", err)
390 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
391 return err
392 }
393 return err
394 }
395
396 if dhcpLayer.Operation == layers.DHCPOpReply {
397 if dhcpMessageType == layers.DHCPMsgTypeOffer {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700398 offeredIp := dhcpLayer.YourClientIP
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700399 if err := sendDHCPRequest(ponPortId, onuId, serialNumber, portNo, onuStateMachine, onuHwAddress, offeredIp, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700400 dhcpLogger.WithFields(log.Fields{
401 "OnuId": onuId,
402 "IntfId": ponPortId,
403 "OnuSn": serialNumber,
404 }).Errorf("Can't send DHCP Request: %s", err)
405 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
406 return err
407 }
408 return err
409 }
410 if err := onuStateMachine.Event("dhcp_request_sent"); err != nil {
411 dhcpLogger.WithFields(log.Fields{
412 "OnuId": onuId,
413 "IntfId": ponPortId,
414 "OnuSn": serialNumber,
415 }).Errorf("Error while transitioning ONU State %v", err)
416 }
417
418 } else if dhcpMessageType == layers.DHCPMsgTypeAck {
419 // NOTE once the ack is received we don't need to do anything but change the state
420 if err := onuStateMachine.Event("dhcp_ack_received"); 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 dhcpLogger.WithFields(log.Fields{
428 "OnuId": onuId,
429 "IntfId": ponPortId,
430 "OnuSn": serialNumber,
431 }).Infof("DHCP State machine completed")
432 }
433 // NOTE do we need to care about DHCPMsgTypeRelease??
434 } else {
435 dhcpLogger.WithFields(log.Fields{
436 "OnuId": onuId,
437 "IntfId": ponPortId,
438 "OnuSn": serialNumber,
439 }).Warnf("Unsupported DHCP Operation: %s", dhcpLayer.Operation.String())
440 }
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700441
Matteo Scandolo075b1892019-10-07 12:11:07 -0700442 return nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700443}
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700444
445// This method handle the BBR DHCP Packets
446// BBR does not need to do anything but forward the packets in the correct direction
447func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, sTag int, macAddress net.HardwareAddr, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
448
449 // check if the packet is going:
450 // - outgouing: toward the DHCP
451 // - incoming: toward the ONU
452 isIncoming := packetHandlers.IsIncomingPacket(pkt)
453 log.Tracef("Is Incoming: %t", isIncoming)
454
455 dhcpType, err := GetDhcpPacketType(pkt)
456 if err != nil {
457 log.WithFields(log.Fields{
458 "err": err,
459 }).Fatalf("Can't find DHCP type for packet")
460 }
461
462 srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
463 dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
464
465 if isIncoming == true {
466
467 onuPacket := openolt.OnuPacket{
468 IntfId: ponPortId,
469 OnuId: onuId,
470 PortNo: onuId,
471 GemportId: 1,
472 Pkt: pkt.Data(),
473 }
474
475 if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
476 log.WithFields(log.Fields{
477 "OnuId": onuId,
478 "IntfId": ponPortId,
479 "OnuSn": serialNumber,
480 "Type": dhcpType,
481 "error": err,
482 }).Error("Failed to send DHCP packet to the ONU")
483 }
484
485 log.WithFields(log.Fields{
486 "OnuId": onuId,
487 "IntfId": ponPortId,
488 "OnuSn": serialNumber,
489 "Type": dhcpType,
490 "DstMac": dstMac,
491 "SrcMac": srcMac,
492 "OnuMac": macAddress,
493 }).Infof("Sent DHCP packet to the ONU")
494
495 // TODO: signal that the ONU has completed
496 dhcpLayer, _ := GetDhcpLayer(pkt)
497 dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
498 if dhcpMessageType == layers.DHCPMsgTypeAck {
499 doneChannel <- true
500 }
501
502 } else {
503 // double tag the packet and send it to the NNI
504 // NOTE do we need this in the HandleDHCP Packet?
505 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(sTag, sTag, pkt)
506 if err != nil {
507 log.Error("Failt to add double tag to packet")
508 }
509
510 pkt := openolt.UplinkPacket{
511 IntfId: 0, // BBSim does not care about which NNI, it has only one
512 Pkt: doubleTaggedPkt.Data(),
513 }
514 if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
515 log.WithFields(log.Fields{
516 "OnuId": onuId,
517 "IntfId": ponPortId,
518 "OnuSn": serialNumber,
519 "Type": dhcpType,
520 "error": err,
521 }).Error("Failed to send DHCP packet out of the NNI Port")
522 }
523 log.WithFields(log.Fields{
524 "OnuId": onuId,
525 "IntfId": ponPortId,
526 "OnuSn": serialNumber,
527 "Type": dhcpType,
528 "DstMac": dstMac,
529 "SrcMac": srcMac,
530 "OnuMac": macAddress,
531 }).Infof("Sent DHCP packet out of the NNI Port")
532 }
533 return nil
534}