blob: 227ce8ea7aac699508321b9ce7d7c1b53e15d02e [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"
32 omci "github.com/opencord/omci-sim"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080033 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070034 log "github.com/sirupsen/logrus"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070035)
36
Matteo Scandolo075b1892019-10-07 12:11:07 -070037var GetGemPortId = omci.GetGemPortId
38
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070039var dhcpLogger = log.WithFields(log.Fields{
40 "module": "DHCP",
41})
42
43var defaultParamsRequestList = []layers.DHCPOpt{
44 layers.DHCPOptSubnetMask,
45 layers.DHCPOptBroadcastAddr,
46 layers.DHCPOptTimeOffset,
47 layers.DHCPOptRouter,
48 layers.DHCPOptDomainName,
49 layers.DHCPOptDNS,
50 layers.DHCPOptDomainSearch,
51 layers.DHCPOptHostname,
52 layers.DHCPOptNetBIOSTCPNS,
53 layers.DHCPOptNetBIOSTCPScope,
54 layers.DHCPOptInterfaceMTU,
55 layers.DHCPOptClasslessStaticRoute,
56 layers.DHCPOptNTPServers,
57}
58
Matteo Scandolo378b8c92020-04-16 14:34:22 -070059func createDefaultDHCPReq(oltId int, intfId uint32, onuId uint32, mac net.HardwareAddr) layers.DHCPv4 {
Matteo Scandolofe9ac252019-10-25 11:40:17 -070060 // NOTE we want to generate a unique XID, the easiest way is to concat the PON ID and the ONU ID
61 // we increment them by one otherwise:
Matteo Scandolo378b8c92020-04-16 14:34:22 -070062 // - OLT: 0 PON: 0 ONU: 62 = 062 -> 62
63 // - OLT: 0 PON: 6 ONU: 2 = 62 -> 62
64 xid, err := strconv.Atoi(fmt.Sprintf("%d%d%d", oltId+1, intfId+1, onuId+1))
Matteo Scandolofe9ac252019-10-25 11:40:17 -070065 if err != nil {
66 log.Fatal("Can't generate unique XID for ONU")
67 }
68
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070069 return layers.DHCPv4{
70 Operation: layers.DHCPOpRequest,
71 HardwareType: layers.LinkTypeEthernet,
72 HardwareLen: 6,
73 HardwareOpts: 0,
Matteo Scandolofe9ac252019-10-25 11:40:17 -070074 Xid: uint32(xid),
Matteo Scandolo40e067f2019-10-16 16:59:41 -070075 ClientHWAddr: mac,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070076 }
77}
78
Matteo Scandolofe9ac252019-10-25 11:40:17 -070079func createDefaultOpts(intfId uint32, onuId uint32) []layers.DHCPOption {
80 hostname := []byte(fmt.Sprintf("%d.%d.bbsim.onf.org", intfId, onuId))
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070081 opts := []layers.DHCPOption{}
82 opts = append(opts, layers.DHCPOption{
83 Type: layers.DHCPOptHostname,
84 Data: hostname,
85 Length: uint8(len(hostname)),
86 })
87
88 bytes := []byte{}
89 for _, option := range defaultParamsRequestList {
90 bytes = append(bytes, byte(option))
91 }
92
93 opts = append(opts, layers.DHCPOption{
94 Type: layers.DHCPOptParamsRequest,
95 Data: bytes,
96 Length: uint8(len(bytes)),
97 })
98 return opts
99}
100
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700101func createDHCPDisc(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
102 dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700103 defaultOpts := createDefaultOpts(intfId, onuId)
Shrey Baid688b4242020-07-10 20:40:10 +0530104 dhcpLayer.Options = append([]layers.DHCPOption{{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700105 Type: layers.DHCPOptMessageType,
106 Data: []byte{byte(layers.DHCPMsgTypeDiscover)},
107 Length: 1,
108 }}, defaultOpts...)
109
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700110 data := []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700111 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 -0700112 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
113 Type: layers.DHCPOptClientID,
114 Data: data,
115 Length: uint8(len(data)),
116 })
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700117
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700118 return &dhcpLayer
119}
120
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700121func createDHCPReq(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
122 dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700123 defaultOpts := createDefaultOpts(intfId, onuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700124
125 dhcpLayer.Options = append(defaultOpts, layers.DHCPOption{
126 Type: layers.DHCPOptMessageType,
127 Data: []byte{byte(layers.DHCPMsgTypeRequest)},
128 Length: 1,
129 })
130
131 data := []byte{182, 21, 0, 128}
132 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
133 Type: layers.DHCPOptServerID,
134 Data: data,
135 Length: uint8(len(data)),
136 })
137
138 data = []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700139 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700140 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
141 Type: layers.DHCPOptClientID,
142 Data: data,
143 Length: uint8(len(data)),
144 })
145
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700146 // 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 -0700147 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
148 Type: layers.DHCPOptRequestIP,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700149 Data: offeredIp,
150 Length: uint8(len(offeredIp)),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700151 })
152 return &dhcpLayer
153}
154
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800155func serializeDHCPPacket(intfId uint32, onuId uint32, cTag int, srcMac net.HardwareAddr, dhcp *layers.DHCPv4) ([]byte, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700156 buffer := gopacket.NewSerializeBuffer()
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800157
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700158 options := gopacket.SerializeOptions{
159 ComputeChecksums: true,
160 FixLengths: true,
161 }
162
163 ethernetLayer := &layers.Ethernet{
164 SrcMAC: srcMac,
165 DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
166 EthernetType: layers.EthernetTypeIPv4,
167 }
168
169 ipLayer := &layers.IPv4{
170 Version: 4,
171 TOS: 0x10,
172 TTL: 128,
173 SrcIP: []byte{0, 0, 0, 0},
174 DstIP: []byte{255, 255, 255, 255},
175 Protocol: layers.IPProtocolUDP,
176 }
177
178 udpLayer := &layers.UDP{
179 SrcPort: 68,
180 DstPort: 67,
181 }
182
Shrey Baid688b4242020-07-10 20:40:10 +0530183 _ = udpLayer.SetNetworkLayerForChecksum(ipLayer)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700184 if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800185 dhcpLogger.Error("SerializeLayers")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700186 return nil, err
187 }
188
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800189 untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
190
191 taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt)
192 if err != nil {
193 dhcpLogger.Error("TagPacket")
194 return nil, err
195 }
196
197 return gopacket.Payload(taggedPkt.Data()), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700198}
199
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700200func GetDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700201 layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
202 dhcp, _ := layerDHCP.(*layers.DHCPv4)
203 if dhcp == nil {
204 return nil, errors.New("Failed-to-extract-DHCP-layer")
205 }
206 return dhcp, nil
207}
208
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700209func GetDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700210 for _, option := range dhcp.Options {
211 if option.Type == layers.DHCPOptMessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700212 if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeDiscover)}) {
213 return layers.DHCPMsgTypeDiscover, nil
214 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700215 return layers.DHCPMsgTypeOffer, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700216 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRequest)}) {
217 return layers.DHCPMsgTypeRequest, nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700218 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeAck)}) {
219 return layers.DHCPMsgTypeAck, nil
220 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRelease)}) {
221 return layers.DHCPMsgTypeRelease, nil
222 } else {
223 msg := fmt.Sprintf("This type %x is not supported", option.Data)
224 return 0, errors.New(msg)
225 }
226 }
227 }
228 return 0, errors.New("Failed to extract MsgType from dhcp")
229}
230
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700231// returns the DHCP Layer type or error if it's not a DHCP Packet
232func GetDhcpPacketType(pkt gopacket.Packet) (string, error) {
233 dhcpLayer, err := GetDhcpLayer(pkt)
234 if err != nil {
235 return "", err
236 }
237 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
238 if err != nil {
239 return "", err
240 }
241
242 return dhcpMessageType.String(), nil
243}
244
Matteo Scandolo27428702019-10-11 16:21:16 -0700245func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, stream bbsim.Stream) error {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700246 // FIXME unify sendDHCPPktIn and sendEapolPktIn methods
Matteo Scandolo075b1892019-10-07 12:11:07 -0700247 gemid, err := GetGemPortId(msg.IntfId, msg.OnuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700248 if err != nil {
249 dhcpLogger.WithFields(log.Fields{
250 "OnuId": msg.OnuId,
251 "IntfId": msg.IntfId,
252 }).Errorf("Can't retrieve GemPortId: %s", err)
253 return err
254 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700255
256 log.WithFields(log.Fields{
Shrey Baid688b4242020-07-10 20:40:10 +0530257 "OnuId": msg.OnuId,
258 "IntfId": msg.IntfId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700259 "GemPort": gemid,
Shrey Baid688b4242020-07-10 20:40:10 +0530260 "Type": "DHCP",
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700261 }).Trace("sending-pkt")
262
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700263 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
Matteo Scandolo27428702019-10-11 16:21:16 -0700264 IntfType: "pon",
265 IntfId: msg.IntfId,
266 GemportId: uint32(gemid),
267 Pkt: msg.Bytes,
268 PortNo: portNo,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700269 }}
270
271 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
272 dhcpLogger.Errorf("Fail to send DHCP PktInd indication. %v", err)
273 return err
274 }
275 return nil
276}
277
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700278func 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 {
279 dhcp := createDHCPReq(oltId, ponPortId, onuId, onuHwAddress, offeredIp)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800280 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700281
282 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700283 dhcpLogger.WithFields(log.Fields{
284 "OnuId": onuId,
285 "IntfId": ponPortId,
286 "OnuSn": serialNumber,
287 "OfferedIp": offeredIp.String(),
288 }).Errorf("Cannot serializeDHCPPacket: %s", err)
289 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
290 return err
291 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700292 return err
293 }
294 // NOTE I don't think we need to tag the packet
295 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
296
297 msg := bbsim.ByteMsg{
298 IntfId: ponPortId,
299 OnuId: onuId,
300 Bytes: pkt,
301 }
302
Matteo Scandolo27428702019-10-11 16:21:16 -0700303 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700304 dhcpLogger.WithFields(log.Fields{
305 "OnuId": onuId,
306 "IntfId": ponPortId,
307 "OnuSn": serialNumber,
308 }).Errorf("Cannot sendDHCPPktIn: %s", err)
309 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
310 return err
311 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700312 return err
313 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700314
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700315 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700316 "OnuId": onuId,
317 "IntfId": ponPortId,
318 "OnuSn": serialNumber,
319 "OfferedIp": offeredIp.String(),
320 }).Infof("DHCPRequest Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700321 return nil
322}
323
Matteo Scandolo075b1892019-10-07 12:11:07 -0700324func updateDhcpFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
325 if err := onuStateMachine.Event("dhcp_failed"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700326 dhcpLogger.WithFields(log.Fields{
327 "OnuId": onuId,
328 "IntfId": ponPortId,
329 "OnuSn": serialNumber,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700330 }).Errorf("Error while transitioning ONU State %v", err)
331 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700332 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700333 return nil
334}
335
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700336func SendDHCPDiscovery(oltId int, ponPortId uint32, onuId uint32, serialNumber string, portNo uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr, cTag int, stream bbsim.Stream) error {
337 dhcp := createDHCPDisc(oltId, ponPortId, onuId, onuHwAddress)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800338 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp)
339
Matteo Scandolo075b1892019-10-07 12:11:07 -0700340 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700341 dhcpLogger.WithFields(log.Fields{
342 "OnuId": onuId,
343 "IntfId": ponPortId,
344 "OnuSn": serialNumber,
345 }).Errorf("Cannot serializeDHCPPacket: %s", err)
346 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
347 return err
348 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700349 return err
350 }
351 // NOTE I don't think we need to tag the packet
352 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
353
354 msg := bbsim.ByteMsg{
355 IntfId: ponPortId,
356 OnuId: onuId,
357 Bytes: pkt,
358 }
359
Matteo Scandolo27428702019-10-11 16:21:16 -0700360 if err := sendDHCPPktIn(msg, portNo, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700361 dhcpLogger.WithFields(log.Fields{
362 "OnuId": onuId,
363 "IntfId": ponPortId,
364 "OnuSn": serialNumber,
365 }).Errorf("Cannot sendDHCPPktIn: %s", err)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700366 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
367 return err
368 }
369 return err
370 }
371 dhcpLogger.WithFields(log.Fields{
372 "OnuId": onuId,
373 "IntfId": ponPortId,
374 "OnuSn": serialNumber,
375 }).Infof("DHCPDiscovery Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700376
377 if err := onuStateMachine.Event("dhcp_discovery_sent"); err != nil {
378 dhcpLogger.WithFields(log.Fields{
379 "OnuId": onuId,
380 "IntfId": ponPortId,
381 "OnuSn": serialNumber,
382 }).Errorf("Error while transitioning ONU State %v", err)
383 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700384 return nil
385}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700386
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700387// FIXME cTag is not used here
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700388func 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 -0700389
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700390 dhcpLayer, err := GetDhcpLayer(pkt)
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 Layer from Packet: %v", err)
397 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
398 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700399 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700400 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700401 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700402 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700403 if err != nil {
404 dhcpLogger.WithFields(log.Fields{
405 "OnuId": onuId,
406 "IntfId": ponPortId,
407 "OnuSn": serialNumber,
408 }).Errorf("Can't get DHCP Message Type from DHCP Layer: %v", err)
409 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
410 return err
411 }
412 return err
413 }
414
415 if dhcpLayer.Operation == layers.DHCPOpReply {
416 if dhcpMessageType == layers.DHCPMsgTypeOffer {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700417 offeredIp := dhcpLayer.YourClientIP
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700418 if err := sendDHCPRequest(oltId, ponPortId, onuId, serialNumber, portNo, cTag, onuStateMachine, onuHwAddress, offeredIp, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700419 dhcpLogger.WithFields(log.Fields{
420 "OnuId": onuId,
421 "IntfId": ponPortId,
422 "OnuSn": serialNumber,
423 }).Errorf("Can't send DHCP Request: %s", err)
424 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
425 return err
426 }
427 return err
428 }
429 if err := onuStateMachine.Event("dhcp_request_sent"); err != nil {
430 dhcpLogger.WithFields(log.Fields{
431 "OnuId": onuId,
432 "IntfId": ponPortId,
433 "OnuSn": serialNumber,
434 }).Errorf("Error while transitioning ONU State %v", err)
435 }
436
437 } else if dhcpMessageType == layers.DHCPMsgTypeAck {
438 // NOTE once the ack is received we don't need to do anything but change the state
439 if err := onuStateMachine.Event("dhcp_ack_received"); err != nil {
440 dhcpLogger.WithFields(log.Fields{
441 "OnuId": onuId,
442 "IntfId": ponPortId,
443 "OnuSn": serialNumber,
444 }).Errorf("Error while transitioning ONU State %v", err)
445 }
446 dhcpLogger.WithFields(log.Fields{
447 "OnuId": onuId,
448 "IntfId": ponPortId,
449 "OnuSn": serialNumber,
450 }).Infof("DHCP State machine completed")
451 }
452 // NOTE do we need to care about DHCPMsgTypeRelease??
453 } else {
454 dhcpLogger.WithFields(log.Fields{
455 "OnuId": onuId,
456 "IntfId": ponPortId,
457 "OnuSn": serialNumber,
458 }).Warnf("Unsupported DHCP Operation: %s", dhcpLayer.Operation.String())
459 }
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700460
Matteo Scandolo075b1892019-10-07 12:11:07 -0700461 return nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700462}
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700463
464// This method handle the BBR DHCP Packets
465// BBR does not need to do anything but forward the packets in the correct direction
466func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, sTag int, macAddress net.HardwareAddr, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
467
468 // check if the packet is going:
469 // - outgouing: toward the DHCP
470 // - incoming: toward the ONU
471 isIncoming := packetHandlers.IsIncomingPacket(pkt)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800472 dhcpLogger.Tracef("Is Incoming: %t", isIncoming)
473
474 pkt, err := packetHandlers.PopSingleTag(pkt)
475 if err != nil {
476 dhcpLogger.WithFields(log.Fields{
477 "OnuId": onuId,
478 "IntfId": ponPortId,
479 "OnuSn": serialNumber,
480 "error": err,
481 }).Fatalf("Can't untag packet")
482 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700483
484 dhcpType, err := GetDhcpPacketType(pkt)
485 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800486 dhcpLogger.WithFields(log.Fields{
487 "OnuId": onuId,
488 "IntfId": ponPortId,
489 "OnuSn": serialNumber,
490 "error": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700491 }).Fatalf("Can't find DHCP type for packet")
492 }
493
494 srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
495 dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
496
Shrey Baid688b4242020-07-10 20:40:10 +0530497 if isIncoming {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700498
499 onuPacket := openolt.OnuPacket{
500 IntfId: ponPortId,
501 OnuId: onuId,
502 PortNo: onuId,
503 GemportId: 1,
504 Pkt: pkt.Data(),
505 }
506
507 if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
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 "error": err,
514 }).Error("Failed to send DHCP packet to the ONU")
515 }
516
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800517 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700518 "OnuId": onuId,
519 "IntfId": ponPortId,
520 "OnuSn": serialNumber,
521 "Type": dhcpType,
522 "DstMac": dstMac,
523 "SrcMac": srcMac,
524 "OnuMac": macAddress,
525 }).Infof("Sent DHCP packet to the ONU")
526
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700527 dhcpLayer, _ := GetDhcpLayer(pkt)
528 dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
529 if dhcpMessageType == layers.DHCPMsgTypeAck {
530 doneChannel <- true
531 }
532
533 } else {
534 // double tag the packet and send it to the NNI
535 // NOTE do we need this in the HandleDHCP Packet?
536 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(sTag, sTag, pkt)
537 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800538 dhcpLogger.WithFields(log.Fields{
539 "OnuId": onuId,
540 "IntfId": ponPortId,
541 "OnuSn": serialNumber,
542 "Type": dhcpType,
543 "error": err,
544 }).Error("Failed to add double tag to packet")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700545 }
546
547 pkt := openolt.UplinkPacket{
548 IntfId: 0, // BBSim does not care about which NNI, it has only one
549 Pkt: doubleTaggedPkt.Data(),
550 }
551 if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800552 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700553 "OnuId": onuId,
554 "IntfId": ponPortId,
555 "OnuSn": serialNumber,
556 "Type": dhcpType,
557 "error": err,
558 }).Error("Failed to send DHCP packet out of the NNI Port")
559 }
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800560 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700561 "OnuId": onuId,
562 "IntfId": ponPortId,
563 "OnuSn": serialNumber,
564 "Type": dhcpType,
565 "DstMac": dstMac,
566 "SrcMac": srcMac,
567 "OnuMac": macAddress,
568 }).Infof("Sent DHCP packet out of the NNI Port")
569 }
570 return nil
571}